(index<- )        ./libsync/future.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Sat Apr 19 11:22:39 2014
   1  // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  /*!
  12   * A type representing values that may be computed concurrently and
  13   * operations for working with them.
  14   *
  15   * # Example
  16   *
  17   * ```rust
  18   * use sync::Future;
  19   * # fn fib(n: uint) -> uint {42};
  20   * # fn make_a_sandwich() {};
  21   * let mut delayed_fib = Future::spawn(proc() { fib(5000) });
  22   * make_a_sandwich();
  23   * println!("fib(5000) = {}", delayed_fib.get())
  24   * ```
  25   */
  26  
  27  #![allow(missing_doc)]
  28  
  29  use std::mem::replace;
  30  
  31  /// A type encapsulating the result of a computation which may not be complete
  32  pub struct Future<A> {
  33      state: FutureState<A>,
  34  }
  35  
  36  enum FutureState<A> {
  37      Pending(proc():Send -> A),
  38      Evaluating,
  39      Forced(A)
  40  }
  41  
  42  /// Methods on the `future` type
  43  impl<A:Clone> Future<A> {
  44      pub fn get(&mut self) -> A {
  45          //! Get the value of the future.
  46          (*(self.get_ref())).clone()
  47      }
  48  }
  49  
  50  impl<A> Future<A> {
  51      /// Gets the value from this future, forcing evaluation.
  52      pub fn unwrap(mut self) -> A {
  53          self.get_ref();
  54          let state = replace(&mut self.state, Evaluating);
  55          match state {
  56              Forced(v) => v,
  57              _ => fail!( "Logic error." ),
  58          }
  59      }
  60  
  61      pub fn get_ref<'a>(&'a mut self) -> &'a A {
  62          /*!
  63          * Executes the future's closure and then returns a reference
  64          * to the result.  The reference lasts as long as
  65          * the future.
  66          */
  67          match self.state {
  68              Forced(ref v) => return v,
  69              Evaluating => fail!("Recursive forcing of future!"),
  70              Pending(_) => {
  71                  match replace(&mut self.state, Evaluating) {
  72                      Forced(_) | Evaluating => fail!("Logic error."),
  73                      Pending(f) => {
  74                          self.state = Forced(f());
  75                          self.get_ref()
  76                      }
  77                  }
  78              }
  79          }
  80      }
  81  
  82      pub fn from_value(valA) -> Future<A> {
  83          /*!
  84           * Create a future from a value.
  85           *
  86           * The value is immediately available and calling `get` later will
  87           * not block.
  88           */
  89  
  90          Future {state: Forced(val)}
  91      }
  92  
  93      pub fn from_fn(fproc():Send -> A) -> Future<A> {
  94          /*!
  95           * Create a future from a function.
  96           *
  97           * The first time that the value is requested it will be retrieved by
  98           * calling the function.  Note that this function is a local
  99           * function. It is not spawned into another task.
 100           */
 101  
 102          Future {state: Pending(f)}
 103      }
 104  }
 105  
 106  impl<A:Send> Future<A> {
 107      pub fn from_receiver(rxReceiver<A>) -> Future<A> {
 108          /*!
 109           * Create a future from a port
 110           *
 111           * The first time that the value is requested the task will block
 112           * waiting for the result to be received on the port.
 113           */
 114  
 115          Future::from_fn(proc() {
 116              rx.recv()
 117          })
 118      }
 119  
 120      pub fn spawn(blkproc():Send -> A) -> Future<A> {
 121          /*!
 122           * Create a future from a unique closure.
 123           *
 124           * The closure will be run in a new task and its result used as the
 125           * value of the future.
 126           */
 127  
 128          let (tx, rx) = channel();
 129  
 130          spawn(proc() {
 131              tx.send(blk());
 132          });
 133  
 134          Future::from_receiver(rx)
 135      }
 136  }
 137  
 138  #[cfg(test)]
 139  mod test {
 140      use future::Future;
 141  
 142      use std::task;
 143  
 144      #[test]
 145      fn test_from_value() {
 146          let mut f = Future::from_value("snail".to_owned());
 147          assert_eq!(f.get(), "snail".to_owned());
 148      }
 149  
 150      #[test]
 151      fn test_from_receiver() {
 152          let (tx, rx) = channel();
 153          tx.send("whale".to_owned());
 154          let mut f = Future::from_receiver(rx);
 155          assert_eq!(f.get(), "whale".to_owned());
 156      }
 157  
 158      #[test]
 159      fn test_from_fn() {
 160          let mut f = Future::from_fn(proc() "brail".to_owned());
 161          assert_eq!(f.get(), "brail".to_owned());
 162      }
 163  
 164      #[test]
 165      fn test_interface_get() {
 166          let mut f = Future::from_value("fail".to_owned());
 167          assert_eq!(f.get(), "fail".to_owned());
 168      }
 169  
 170      #[test]
 171      fn test_interface_unwrap() {
 172          let f = Future::from_value("fail".to_owned());
 173          assert_eq!(f.unwrap(), "fail".to_owned());
 174      }
 175  
 176      #[test]
 177      fn test_get_ref_method() {
 178          let mut f = Future::from_value(22);
 179          assert_eq!(*f.get_ref(), 22);
 180      }
 181  
 182      #[test]
 183      fn test_spawn() {
 184          let mut f = Future::spawn(proc() "bale".to_owned());
 185          assert_eq!(f.get(), "bale".to_owned());
 186      }
 187  
 188      #[test]
 189      #[should_fail]
 190      fn test_futurefail() {
 191          let mut f = Future::spawn(proc() fail!());
 192          let _x: ~str = f.get();
 193      }
 194  
 195      #[test]
 196      fn test_sendable_future() {
 197          let expected = "schlorf";
 198          let f = Future::spawn(proc() { expected });
 199          task::spawn(proc() {
 200              let mut f = f;
 201              let actual = f.get();
 202              assert_eq!(actual, expected);
 203          });
 204      }
 205  }