diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md
index aa63a0112d02..e1f70a19e52e 100644
--- a/doc/tutorial-tasks.md
+++ b/doc/tutorial-tasks.md
@@ -280,7 +280,7 @@ fn fib(n: uint) -> uint {
12586269025
}
-let mut delayed_fib = extra::future::spawn (|| fib(50) );
+let mut delayed_fib = extra::future::Future::spawn (|| fib(50) );
make_a_sandwich();
println(fmt!("fib(50) = %?", delayed_fib.get()))
~~~
@@ -304,7 +304,7 @@ fn partial_sum(start: uint) -> f64 {
}
fn main() {
- let mut futures = vec::from_fn(1000, |ind| do extra::future::spawn { partial_sum(ind) });
+ let mut futures = vec::from_fn(1000, |ind| do extra::future::Future::spawn { partial_sum(ind) });
let mut final_res = 0f64;
for ft in futures.mut_iter() {
diff --git a/src/libextra/fileinput.rs b/src/libextra/fileinput.rs
index 25d11d413c06..3ce58b58db6d 100644
--- a/src/libextra/fileinput.rs
+++ b/src/libextra/fileinput.rs
@@ -420,7 +420,6 @@ mod test {
use std::rt::io;
use std::rt::io::Writer;
use std::rt::io::file;
- use std::uint;
use std::vec;
fn make_file(path : &Path, contents: &[~str]) {
diff --git a/src/libextra/future.rs b/src/libextra/future.rs
index 74a551c6f6d5..4e8bc37891dc 100644
--- a/src/libextra/future.rs
+++ b/src/libextra/future.rs
@@ -25,27 +25,16 @@
#[allow(missing_doc)];
-
-use std::cast;
use std::cell::Cell;
use std::comm::{PortOne, oneshot};
use std::task;
use std::util::replace;
-#[doc = "The future type"]
+/// A type encapsulating the result of a computation which may not be complete
pub struct Future {
priv state: FutureState,
}
-// n.b. It should be possible to get rid of this.
-// Add a test, though -- tjc
-// FIXME(#2829) -- futures should not be copyable, because they close
-// over ~fn's that have pipes and so forth within!
-#[unsafe_destructor]
-impl Drop for Future {
- fn drop(&mut self) {}
-}
-
enum FutureState {
Pending(~fn() -> A),
Evaluating,
@@ -71,96 +60,105 @@ impl Future {
_ => fail!( "Logic error." ),
}
}
-}
-impl Future {
pub fn get_ref<'a>(&'a mut self) -> &'a A {
/*!
* Executes the future's closure and then returns a borrowed
* pointer to the result. The borrowed pointer lasts as long as
* the future.
*/
- unsafe {
- {
- match self.state {
- Forced(ref mut v) => { return cast::transmute(v); }
- Evaluating => fail!("Recursive forcing of future!"),
- Pending(_) => {}
- }
- }
- {
- let state = replace(&mut self.state, Evaluating);
- match state {
+ match self.state {
+ Forced(ref v) => return v,
+ Evaluating => fail!("Recursive forcing of future!"),
+ Pending(_) => {
+ match replace(&mut self.state, Evaluating) {
Forced(_) | Evaluating => fail!("Logic error."),
Pending(f) => {
self.state = Forced(f());
- cast::transmute(self.get_ref())
+ self.get_ref()
}
}
}
}
}
-}
-pub fn from_value(val: A) -> Future {
- /*!
- * Create a future from a value.
- *
- * The value is immediately available and calling `get` later will
- * not block.
- */
+ pub fn from_value(val: A) -> Future {
+ /*!
+ * Create a future from a value.
+ *
+ * The value is immediately available and calling `get` later will
+ * not block.
+ */
- Future {state: Forced(val)}
-}
+ Future {state: Forced(val)}
+ }
-pub fn from_port(port: PortOne) -> Future {
- /*!
- * 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.
- */
+ pub fn from_fn(f: ~fn() -> A) -> Future {
+ /*!
+ * Create a future from a function.
+ *
+ * The first time that the value is requested it will be retrieved by
+ * calling the function. Note that this function is a local
+ * function. It is not spawned into another task.
+ */
- let port = Cell::new(port);
- do from_fn {
- port.take().recv()
+ Future {state: Pending(f)}
}
}
-pub fn from_fn(f: ~fn() -> A) -> Future {
- /*!
- * Create a future from a function.
- *
- * The first time that the value is requested it will be retrieved by
- * calling the function. Note that this function is a local
- * function. It is not spawned into another task.
- */
+impl Future {
+ pub fn from_port(port: PortOne) -> Future {
+ /*!
+ * 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 {state: Pending(f)}
-}
-
-pub fn spawn(blk: ~fn() -> A) -> Future {
- /*!
- * 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 (port, chan) = oneshot();
-
- let chan = Cell::new(chan);
- do task::spawn {
- let chan = chan.take();
- chan.send(blk());
+ let port = Cell::new(port);
+ do Future::from_fn {
+ port.take().recv()
+ }
}
- return from_port(port);
+ pub fn spawn(blk: ~fn() -> A) -> Future {
+ /*!
+ * 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 (port, chan) = oneshot();
+
+ do task::spawn_with(chan) |chan| {
+ chan.send(blk());
+ }
+
+ Future::from_port(port)
+ }
+
+ pub fn spawn_with(v: B, blk: ~fn(B) -> A) -> Future {
+ /*!
+ * Create a future from a unique closure taking one argument.
+ *
+ * The closure and its argument will be moved into a new task. The
+ * closure will be run and its result used as the value of the future.
+ */
+
+ let (port, chan) = oneshot();
+
+ do task::spawn_with((v, chan)) |(v, chan)| {
+ chan.send(blk(v));
+ }
+
+ Future::from_port(port)
+ }
}
#[cfg(test)]
mod test {
- use future::*;
+ use future::Future;
use std::cell::Cell;
use std::comm::oneshot;
@@ -168,7 +166,7 @@ mod test {
#[test]
fn test_from_value() {
- let mut f = from_value(~"snail");
+ let mut f = Future::from_value(~"snail");
assert_eq!(f.get(), ~"snail");
}
@@ -176,51 +174,57 @@ mod test {
fn test_from_port() {
let (po, ch) = oneshot();
ch.send(~"whale");
- let mut f = from_port(po);
+ let mut f = Future::from_port(po);
assert_eq!(f.get(), ~"whale");
}
#[test]
fn test_from_fn() {
- let mut f = from_fn(|| ~"brail");
+ let mut f = Future::from_fn(|| ~"brail");
assert_eq!(f.get(), ~"brail");
}
#[test]
fn test_interface_get() {
- let mut f = from_value(~"fail");
+ let mut f = Future::from_value(~"fail");
assert_eq!(f.get(), ~"fail");
}
#[test]
fn test_interface_unwrap() {
- let f = from_value(~"fail");
+ let f = Future::from_value(~"fail");
assert_eq!(f.unwrap(), ~"fail");
}
#[test]
fn test_get_ref_method() {
- let mut f = from_value(22);
+ let mut f = Future::from_value(22);
assert_eq!(*f.get_ref(), 22);
}
#[test]
fn test_spawn() {
- let mut f = spawn(|| ~"bale");
+ let mut f = Future::spawn(|| ~"bale");
assert_eq!(f.get(), ~"bale");
}
+ #[test]
+ fn test_spawn_with() {
+ let mut f = Future::spawn_with(~"gale", |s| { s });
+ assert_eq!(f.get(), ~"gale");
+ }
+
#[test]
#[should_fail]
fn test_futurefail() {
- let mut f = spawn(|| fail!());
+ let mut f = Future::spawn(|| fail!());
let _x: ~str = f.get();
}
#[test]
fn test_sendable_future() {
let expected = "schlorf";
- let f = Cell::new(do spawn { expected });
+ let f = Cell::new(do Future::spawn { expected });
do task::spawn {
let mut f = f.take();
let actual = f.get();
diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs
index 43a4ecf56168..934943f6fbb4 100644
--- a/src/libextra/glob.rs
+++ b/src/libextra/glob.rs
@@ -512,10 +512,8 @@ impl MatchOptions {
#[cfg(test)]
mod test {
- use std::{io, os, unstable};
- use std::unstable::finally::Finally;
+ use std::os;
use super::*;
- use tempfile;
#[test]
fn test_absolute_pattern() {
diff --git a/src/libextra/par.rs b/src/libextra/par.rs
index 71dddc481ae3..b55143152269 100644
--- a/src/libextra/par.rs
+++ b/src/libextra/par.rs
@@ -14,7 +14,7 @@ use std::num;
use std::ptr;
use std::sys;
use std::vec;
-use future_spawn = future::spawn;
+use future::Future;
/**
* The maximum number of tasks this module will spawn for a single
@@ -55,7 +55,7 @@ fn map_slices(
do xs.as_imm_buf |p, _len| {
let f = f();
let base = base;
- let f = do future_spawn() || {
+ let f = do Future::spawn() || {
unsafe {
let len = end - base;
let slice = (ptr::offset(p, base as int),
diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs
index a1ea5a68c827..fb58e5c2bf02 100644
--- a/src/librustdoc/markdown_writer.rs
+++ b/src/librustdoc/markdown_writer.rs
@@ -20,7 +20,7 @@ use std::result;
use std::run;
use std::str;
use std::task;
-use extra::future;
+use extra::future::Future;
#[deriving(Clone)]
pub enum WriteInstr {
@@ -207,10 +207,10 @@ pub fn future_writer_factory(
(writer_factory, markdown_po)
}
-fn future_writer() -> (Writer, future::Future<~str>) {
+fn future_writer() -> (Writer, Future<~str>) {
let (port, chan) = comm::stream();
let writer: ~fn(instr: WriteInstr) = |instr| chan.send(instr.clone());
- let future = do future::from_fn || {
+ let future = do Future::from_fn || {
let mut res = ~"";
loop {
match port.recv() {
diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs
index dd56d550e61c..b52ba154f435 100644
--- a/src/test/bench/msgsend-ring-mutex-arcs.rs
+++ b/src/test/bench/msgsend-ring-mutex-arcs.rs
@@ -18,7 +18,7 @@
extern mod extra;
use extra::arc;
-use extra::future;
+use extra::future::Future;
use extra::time;
use std::cell::Cell;
use std::os;
@@ -94,7 +94,7 @@ fn main() {
let (new_chan, num_port) = init();
let num_chan2 = Cell::new(num_chan.take());
let num_port = Cell::new(num_port);
- let new_future = do future::spawn() {
+ let new_future = do Future::spawn() {
let num_chan = num_chan2.take();
let num_port1 = num_port.take();
thread_ring(i, msg_per_task, num_chan, num_port1)
diff --git a/src/test/bench/msgsend-ring-rw-arcs.rs b/src/test/bench/msgsend-ring-rw-arcs.rs
index 130bd4e7d16a..e3d0b4912f97 100644
--- a/src/test/bench/msgsend-ring-rw-arcs.rs
+++ b/src/test/bench/msgsend-ring-rw-arcs.rs
@@ -18,7 +18,7 @@
extern mod extra;
use extra::arc;
-use extra::future;
+use extra::future::Future;
use extra::time;
use std::cell::Cell;
use std::os;
@@ -90,7 +90,7 @@ fn main() {
let (new_chan, num_port) = init();
let num_chan2 = Cell::new(num_chan.take());
let num_port = Cell::new(num_port);
- let new_future = do future::spawn {
+ let new_future = do Future::spawn {
let num_chan = num_chan2.take();
let num_port1 = num_port.take();
thread_ring(i, msg_per_task, num_chan, num_port1)
diff --git a/src/test/compile-fail/future_not_copyable.rs b/src/test/compile-fail/future_not_copyable.rs
new file mode 100644
index 000000000000..aef5d0f9b04a
--- /dev/null
+++ b/src/test/compile-fail/future_not_copyable.rs
@@ -0,0 +1,19 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern mod extra;
+
+use extra::future::Future;
+
+fn main() {
+ let f = Future::from_value(());
+ let g = f;
+ f.unwrap(); //~ ERROR use of moved value
+}