Skip to content

Commit ff6b71f

Browse files
committed
core: Add core::future
Futures will be required for upcoming changes to the task API
1 parent 859e025 commit ff6b71f

File tree

2 files changed

+157
-1
lines changed

2 files changed

+157
-1
lines changed

src/libcore/core.rc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,12 @@ mod math;
8080
mod cmath;
8181
mod sys;
8282
mod unsafe;
83+
mod logging;
84+
85+
// Concurrency
8386
mod comm;
8487
mod task;
85-
mod logging;
88+
mod future;
8689

8790
// Compiler support modules
8891

src/libcore/future.rs

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#[doc = "
2+
3+
A type representing values that may be computed concurrently and
4+
operations for working with them.
5+
6+
Example:
7+
8+
> let delayed_fib = future::spawn {|| fib(5000) };
9+
> make_a_sandwitch();
10+
> io::println(#fmt(\"fib(5000) = %?\", delayed_fib.get()))
11+
12+
"];
13+
14+
export future;
15+
export future::{};
16+
export from_value;
17+
export from_port;
18+
export get;
19+
export with;
20+
export spawn;
21+
22+
import either = either::t;
23+
24+
#[doc = "The future type"]
25+
enum future<A> = {
26+
mutable v: either<@A, comm::port<A>>
27+
};
28+
29+
#[doc = "Methods on the `future` type"]
30+
impl future<A:send> for future<A> {
31+
32+
fn get() -> A {
33+
#[doc = "Get the value of the future"];
34+
35+
get(self)
36+
}
37+
38+
fn with<B>(blk: fn(A) -> B) -> B {
39+
#[doc = "Work with the value without copying it"];
40+
41+
with(self, blk)
42+
}
43+
}
44+
45+
fn from_value<A>(+val: A) -> future<A> {
46+
#[doc = "
47+
48+
Create a future from a value. The value is immediately available
49+
and calling `get` later will not block.
50+
51+
"];
52+
53+
future({
54+
mutable v: either::left(@val)
55+
})
56+
}
57+
58+
fn from_port<A>(-port: comm::port<A>) -> future<A> {
59+
#[doc = "
60+
61+
Create a future from a port. The first time that the value is
62+
requested the task will block waiting for the result to be
63+
received on the port.
64+
65+
"];
66+
67+
future({
68+
mutable v: either::right(port)
69+
})
70+
}
71+
72+
fn get<A:send>(future: future<A>) -> A {
73+
#[doc = "Get the value of the future"];
74+
75+
with(future) {|v| v }
76+
}
77+
78+
fn with<A:send,B>(future: future<A>, blk: fn(A) -> B) -> B {
79+
#[doc = "Work with the value without copying it"];
80+
81+
let v = alt future.v {
82+
either::left(v) { v }
83+
either::right(po) {
84+
let v = @comm::recv(po);
85+
future.v = either::left(v);
86+
v
87+
}
88+
};
89+
blk(*v)
90+
}
91+
92+
fn spawn<A:send>(+blk: fn~() -> A) -> future<A> {
93+
#[doc = "
94+
95+
Create a future from a unique closure. The closure will be run
96+
in a new task and its result used as the value of the future.
97+
98+
"];
99+
100+
let po = comm::port();
101+
let ch = comm::chan(po);
102+
task::spawn {||
103+
comm::send(ch, blk())
104+
};
105+
from_port(po)
106+
}
107+
108+
#[test]
109+
fn test_from_value() {
110+
let f = from_value("snail");
111+
assert get(f) == "snail";
112+
}
113+
114+
#[test]
115+
fn test_from_port() {
116+
let po = comm::port();
117+
let ch = comm::chan(po);
118+
comm::send(ch, "whale");
119+
let f = from_port(po);
120+
assert get(f) == "whale";
121+
}
122+
123+
#[test]
124+
fn test_iface_get() {
125+
let f = from_value("fail");
126+
assert f.get() == "fail";
127+
}
128+
129+
#[test]
130+
fn test_with() {
131+
let f = from_value("nail");
132+
assert with(f) {|v| v} == "nail";
133+
}
134+
135+
#[test]
136+
fn test_iface_with() {
137+
let f = from_value("kale");
138+
assert f.with {|v| v} == "kale";
139+
}
140+
141+
#[test]
142+
fn test_spawn() {
143+
let f = spawn {|| "bale" };
144+
assert get(f) == "bale";
145+
}
146+
147+
#[test]
148+
#[should_fail]
149+
#[ignore(cfg(target_os = "win32"))]
150+
fn test_futurefail() {
151+
let f = spawn {|| fail };
152+
let _x: str = get(f);
153+
}

0 commit comments

Comments
 (0)