17
17
18
18
import either:: Either ;
19
19
import pipes:: recv;
20
+ import unsafe:: copy_lifetime;
20
21
21
22
export Future ;
22
23
export extensions;
@@ -31,18 +32,29 @@ export spawn;
31
32
export future_pipe;
32
33
33
34
#[ doc = "The future type" ]
34
- enum Future < A > = {
35
- mut v : Either <@ A , fn@ ( ) -> A >
36
- } ;
35
+ struct Future < A > {
36
+ /*priv*/ mut state : FutureState < A > ;
37
+ }
37
38
38
- /// Methods on the `future` type
39
- impl < A : copy send> Future < A > {
39
+ priv enum FutureState < A > {
40
+ Pending ( fn @( ) -> A ) ,
41
+ Evaluating ,
42
+ Forced ( A )
43
+ }
40
44
45
+ /// Methods on the `future` type
46
+ impl < A : copy > Future < A > {
41
47
fn get ( ) -> A {
42
48
//! Get the value of the future
43
49
44
50
get ( & self )
45
51
}
52
+ }
53
+
54
+ impl < A > Future < A > {
55
+ fn get_ref ( & self ) -> & self /A {
56
+ get_ref ( self )
57
+ }
46
58
47
59
fn with < B > ( blk : fn ( ( & A ) ) -> B ) -> B {
48
60
//! Work with the value without copying it
@@ -59,9 +71,7 @@ fn from_value<A>(+val: A) -> Future<A> {
59
71
* not block.
60
72
*/
61
73
62
- Future ( {
63
- mut v: either:: Left ( @val)
64
- } )
74
+ Future { state : Forced ( val) }
65
75
}
66
76
67
77
fn from_port < A : send > ( +port : future_pipe:: client:: waiting < A > ) -> Future < A > {
@@ -83,7 +93,7 @@ fn from_port<A:send>(+port: future_pipe::client::waiting<A>) -> Future<A> {
83
93
}
84
94
}
85
95
86
- fn from_fn < A > ( f : fn @ ( ) -> A ) -> Future < A > {
96
+ fn from_fn < A > ( + f : @ fn ( ) -> A ) -> Future < A > {
87
97
/*!
88
98
* Create a future from a function.
89
99
*
@@ -92,9 +102,7 @@ fn from_fn<A>(f: fn@() -> A) -> Future<A> {
92
102
* function. It is not spawned into another task.
93
103
*/
94
104
95
- Future ( {
96
- mut v: either:: Right ( f)
97
- } )
105
+ Future { state : Pending ( f) }
98
106
}
99
107
100
108
fn spawn < A : send > ( +blk : fn ~( ) -> A ) -> Future < A > {
@@ -110,24 +118,54 @@ fn spawn<A:send>(+blk: fn~() -> A) -> Future<A> {
110
118
} ) )
111
119
}
112
120
121
+ fn get_ref < A > ( future : & r/Future < A > ) -> & r /A {
122
+ /*!
123
+ * Executes the future's closure and then returns a borrowed
124
+ * pointer to the result. The borrowed pointer lasts as long as
125
+ * the future.
126
+ */
127
+
128
+ // The unsafety here is to hide the aliases from borrowck, which
129
+ // would otherwise be concerned that someone might reassign
130
+ // `future.state` and cause the value of the future to be freed.
131
+ // But *we* know that once `future.state` is `Forced()` it will
132
+ // never become "unforced"---so we can safely return a pointer
133
+ // into the interior of the Forced() variant which will last as
134
+ // long as the future itself.
135
+
136
+ match future. state {
137
+ Forced ( ref v) => { // v here has type &A, but with a shorter lifetime.
138
+ return unsafe { copy_lifetime ( future, v) } ; // ...extend it.
139
+ }
140
+ Evaluating => {
141
+ fail ~"Recursive forcing of future!";
142
+ }
143
+ Pending(_) => {}
144
+ }
145
+
146
+ let mut state = Evaluating;
147
+ state <-> future.state;
148
+ match move state {
149
+ Forced(_) | Evaluating => {
150
+ fail ~" Logic error. ";
151
+ }
152
+ Pending ( move f) => {
153
+ future. state = Forced ( f ( ) ) ;
154
+ return get_ref ( future) ;
155
+ }
156
+ }
157
+ }
158
+
113
159
fn get < A : copy > ( future : & Future < A > ) -> A {
114
160
//! Get the value of the future
115
161
116
- do with ( future) |v| { * v }
162
+ * get_ref ( future)
117
163
}
118
164
119
165
fn with < A , B > ( future : & Future < A > , blk : fn ( ( & A ) ) -> B ) -> B {
120
166
//! Work with the value without copying it
121
167
122
- let v = match copy future. v {
123
- either:: Left ( v) => v,
124
- either:: Right ( f) => {
125
- let v = @f ( ) ;
126
- future. v = either:: Left ( v) ;
127
- v
128
- }
129
- } ;
130
- blk ( v)
168
+ blk ( get_ref ( future) )
131
169
}
132
170
133
171
proto ! future_pipe (
@@ -152,8 +190,7 @@ fn test_from_port() {
152
190
153
191
#[ test]
154
192
fn test_from_fn ( ) {
155
- let f = fn @( ) -> ~str { ~"brail" } ;
156
- let f = from_fn ( f) ;
193
+ let f = from_fn ( || ~"brail") ;
157
194
assert get( & f) == ~"brail";
158
195
}
159
196
@@ -169,6 +206,18 @@ fn test_with() {
169
206
assert with( & f, |v| * v) == ~"nail";
170
207
}
171
208
209
+ #[ test]
210
+ fn test_get_ref_method ( ) {
211
+ let f = from_value ( 22 ) ;
212
+ assert * f. get_ref ( ) == 22 ;
213
+ }
214
+
215
+ #[ test]
216
+ fn test_get_ref_fn ( ) {
217
+ let f = from_value ( 22 ) ;
218
+ assert * get_ref ( & f) == 22 ;
219
+ }
220
+
172
221
#[ test]
173
222
fn test_interface_with ( ) {
174
223
let f = from_value ( ~"kale") ;
0 commit comments