diff options
| author | bors <bors@rust-lang.org> | 2013-09-19 19:31:13 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-09-19 19:31:13 -0700 |
| commit | 407d179f4e0b625e6911ebaf72c87cd35935fb06 (patch) | |
| tree | 03a0d29757c7b5ba7b3f1eb579b3184174c40fb2 | |
| parent | 570431fcacb115eb0bc3bd9f81977b57173a95ef (diff) | |
| parent | 963707f45d935e938adde9e37b56355a915660bd (diff) | |
| download | rust-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.md | 4 | ||||
| -rw-r--r-- | src/libextra/fileinput.rs | 1 | ||||
| -rw-r--r-- | src/libextra/future.rs | 164 | ||||
| -rw-r--r-- | src/libextra/glob.rs | 4 | ||||
| -rw-r--r-- | src/libextra/par.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/markdown_writer.rs | 6 | ||||
| -rw-r--r-- | src/test/bench/msgsend-ring-mutex-arcs.rs | 4 | ||||
| -rw-r--r-- | src/test/bench/msgsend-ring-rw-arcs.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/future_not_copyable.rs | 19 |
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 +} |
