diff options
| author | Brian Anderson <banderson@mozilla.com> | 2012-02-14 16:39:20 -0800 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2012-02-14 16:45:17 -0800 |
| commit | ff6b71f78bd00a93a91691bb297d6a379cdc50fa (patch) | |
| tree | 9c10da4361d5ca217ca510ec2d1887645c876a36 /src | |
| parent | 859e0256524a1f19ca0c79f518d2bb396355f174 (diff) | |
| download | rust-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.rc | 5 | ||||
| -rw-r--r-- | src/libcore/future.rs | 153 |
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 |
