about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-02-14 16:39:20 -0800
committerBrian Anderson <banderson@mozilla.com>2012-02-14 16:45:17 -0800
commitff6b71f78bd00a93a91691bb297d6a379cdc50fa (patch)
tree9c10da4361d5ca217ca510ec2d1887645c876a36 /src
parent859e0256524a1f19ca0c79f518d2bb396355f174 (diff)
downloadrust-ff6b71f78bd00a93a91691bb297d6a379cdc50fa.tar.gz
rust-ff6b71f78bd00a93a91691bb297d6a379cdc50fa.zip
core: Add core::future
Futures will be required for upcoming changes to the task API
Diffstat (limited to 'src')
-rw-r--r--src/libcore/core.rc5
-rw-r--r--src/libcore/future.rs153
2 files changed, 157 insertions, 1 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index 181e54a95a4..868762a090f 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -80,9 +80,12 @@ mod math;
 mod cmath;
 mod sys;
 mod unsafe;
+mod logging;
+
+// Concurrency
 mod comm;
 mod task;
-mod logging;
+mod future;
 
 // Compiler support modules
 
diff --git a/src/libcore/future.rs b/src/libcore/future.rs
new file mode 100644
index 00000000000..ae90b903518
--- /dev/null
+++ b/src/libcore/future.rs
@@ -0,0 +1,153 @@
+#[doc = "
+
+A type representing values that may be computed concurrently and
+operations for working with them.
+
+Example:
+
+> let delayed_fib = future::spawn {|| fib(5000) };
+> make_a_sandwitch();
+> io::println(#fmt(\"fib(5000) = %?\", delayed_fib.get()))
+
+"];
+
+export future;
+export future::{};
+export from_value;
+export from_port;
+export get;
+export with;
+export spawn;
+
+import either = either::t;
+
+#[doc = "The future type"]
+enum future<A> = {
+    mutable v: either<@A, comm::port<A>>
+};
+
+#[doc = "Methods on the `future` type"]
+impl future<A:send> for future<A> {
+
+    fn get() -> A {
+        #[doc = "Get the value of the future"];
+
+        get(self)
+    }
+
+    fn with<B>(blk: fn(A) -> B) -> B {
+        #[doc = "Work with the value without copying it"];
+
+        with(self, blk)
+    }
+}
+
+fn from_value<A>(+val: A) -> future<A> {
+    #[doc = "
+
+    Create a future from a value. The value is immediately available
+    and calling `get` later will not block.
+
+    "];
+
+    future({
+        mutable v: either::left(@val)
+    })
+}
+
+fn from_port<A>(-port: comm::port<A>) -> future<A> {
+    #[doc = "
+
+    Create a future from a port. The first time that the value is
+    requested the task will block waiting for the result to be
+    received on the port.
+
+    "];
+
+    future({
+        mutable v: either::right(port)
+    })
+}
+
+fn get<A:send>(future: future<A>) -> A {
+    #[doc = "Get the value of the future"];
+
+    with(future) {|v| v }
+}
+
+fn with<A:send,B>(future: future<A>, blk: fn(A) -> B) -> B {
+    #[doc = "Work with the value without copying it"];
+
+    let v = alt future.v {
+      either::left(v) { v }
+      either::right(po) {
+        let v = @comm::recv(po);
+        future.v = either::left(v);
+        v
+      }
+    };
+    blk(*v)
+}
+
+fn spawn<A:send>(+blk: fn~() -> A) -> future<A> {
+    #[doc = "
+
+    Create a future from a unique closure. The closure will be run
+    in a new task and its result used as the value of the future.
+
+    "];
+
+    let po = comm::port();
+    let ch = comm::chan(po);
+    task::spawn {||
+        comm::send(ch, blk())
+    };
+    from_port(po)
+}
+
+#[test]
+fn test_from_value() {
+    let f = from_value("snail");
+    assert get(f) == "snail";
+}
+
+#[test]
+fn test_from_port() {
+    let po = comm::port();
+    let ch = comm::chan(po);
+    comm::send(ch, "whale");
+    let f = from_port(po);
+    assert get(f) == "whale";
+}
+
+#[test]
+fn test_iface_get() {
+    let f = from_value("fail");
+    assert f.get() == "fail";
+}
+
+#[test]
+fn test_with() {
+    let f = from_value("nail");
+    assert with(f) {|v| v} == "nail";
+}
+
+#[test]
+fn test_iface_with() {
+    let f = from_value("kale");
+    assert f.with {|v| v} == "kale";
+}
+
+#[test]
+fn test_spawn() {
+    let f = spawn {|| "bale" };
+    assert get(f) == "bale";
+}
+
+#[test]
+#[should_fail]
+#[ignore(cfg(target_os = "win32"))]
+fn test_futurefail() {
+    let f = spawn {|| fail };
+    let _x: str = get(f);
+}
\ No newline at end of file