about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-09-19 19:31:13 -0700
committerbors <bors@rust-lang.org>2013-09-19 19:31:13 -0700
commit407d179f4e0b625e6911ebaf72c87cd35935fb06 (patch)
tree03a0d29757c7b5ba7b3f1eb579b3184174c40fb2
parent570431fcacb115eb0bc3bd9f81977b57173a95ef (diff)
parent963707f45d935e938adde9e37b56355a915660bd (diff)
downloadrust-407d179f4e0b625e6911ebaf72c87cd35935fb06.tar.gz
rust-407d179f4e0b625e6911ebaf72c87cd35935fb06.zip
auto merge of #9285 : sfackler/rust/future, r=alexcrichton
The `Drop` implementation was used to prevent `Future` from being implicitly copyable. Since `~fn`s are no longer copyable, this is no longer needed. I added a cfail test to make sure that this is actually the case.

I method-ized all of the `Future` creation methods and added a new one, `spawn_with`, which is similar to `task::spawn_with`.

I also got rid of some unused imports in tests.
-rw-r--r--doc/tutorial-tasks.md4
-rw-r--r--src/libextra/fileinput.rs1
-rw-r--r--src/libextra/future.rs164
-rw-r--r--src/libextra/glob.rs4
-rw-r--r--src/libextra/par.rs4
-rw-r--r--src/librustdoc/markdown_writer.rs6
-rw-r--r--src/test/bench/msgsend-ring-mutex-arcs.rs4
-rw-r--r--src/test/bench/msgsend-ring-rw-arcs.rs4
-rw-r--r--src/test/compile-fail/future_not_copyable.rs19
9 files changed, 115 insertions, 95 deletions
diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md
index aa63a0112d0..e1f70a19e52 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 25d11d413c0..3ce58b58db6 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 74a551c6f6d..4e8bc37891d 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<A> {
     priv state: FutureState<A>,
 }
 
-// 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<A> Drop for Future<A> {
-    fn drop(&mut self) {}
-}
-
 enum FutureState<A> {
     Pending(~fn() -> A),
     Evaluating,
@@ -71,96 +60,105 @@ impl<A> Future<A> {
             _ => fail!( "Logic error." ),
         }
     }
-}
 
-impl<A> Future<A> {
     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<A>(val: A) -> Future<A> {
-    /*!
-     * Create a future from a value.
-     *
-     * The value is immediately available and calling `get` later will
-     * not block.
-     */
 
-    Future {state: Forced(val)}
-}
+    pub fn from_value(val: A) -> Future<A> {
+        /*!
+         * Create a future from a value.
+         *
+         * The value is immediately available and calling `get` later will
+         * not block.
+         */
 
-pub fn from_port<A:Send>(port: PortOne<A>) -> Future<A> {
-    /*!
-     * 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: Forced(val)}
+    }
 
-    let port = Cell::new(port);
-    do from_fn {
-        port.take().recv()
+    pub fn from_fn(f: ~fn() -> A) -> Future<A> {
+        /*!
+         * 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.
+         */
+
+        Future {state: Pending(f)}
     }
 }
 
-pub fn from_fn<A>(f: ~fn() -> A) -> Future<A> {
-    /*!
-     * 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<A:Send> Future<A> {
+    pub fn from_port(port: PortOne<A>) -> Future<A> {
+        /*!
+         * 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.
+         */
+
+        let port = Cell::new(port);
+        do Future::from_fn {
+            port.take().recv()
+        }
+    }
 
-    Future {state: Pending(f)}
-}
+    pub fn spawn(blk: ~fn() -> A) -> Future<A> {
+        /*!
+         * 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.
+         */
 
-pub fn spawn<A:Send>(blk: ~fn() -> A) -> Future<A> {
-    /*!
-     * 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 (port, chan) = oneshot();
+        do task::spawn_with(chan) |chan| {
+            chan.send(blk());
+        }
 
-    let chan = Cell::new(chan);
-    do task::spawn {
-        let chan = chan.take();
-        chan.send(blk());
+        Future::from_port(port)
     }
 
-    return from_port(port);
+    pub fn spawn_with<B: Send>(v: B, blk: ~fn(B) -> A) -> Future<A> {
+        /*!
+         * 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 43a4ecf5616..934943f6fbb 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 71dddc481ae..b5514315226 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<A:Clone + Send,B:Clone + Send>(
             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 a1ea5a68c82..fb58e5c2bf0 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 dd56d550e61..b52ba154f43 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 130bd4e7d16..e3d0b4912f9 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 00000000000..aef5d0f9b04
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+}