about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/rt/mod.rs9
-rw-r--r--src/libstd/sync/future.rs31
-rw-r--r--src/libstd/sync/task_pool.rs16
-rw-r--r--src/libstd/sys/unix/process.rs16
-rw-r--r--src/libstd/task.rs128
6 files changed, 115 insertions, 87 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index c2363c9946a..e99aba9b673 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -171,6 +171,8 @@ pub use rustrt::c_str;
 
 pub use unicode::char;
 
+pub use rustrt::thunk;
+
 /* Exported macros */
 
 pub mod macros;
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 5ecd3ff04f1..eb517047ddc 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -52,6 +52,7 @@ use borrow::IntoCow;
 use failure;
 use rustrt;
 use os;
+use thunk::Thunk;
 
 // Reexport some of our utilities which are expected by other crates.
 pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
@@ -87,10 +88,10 @@ static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
 #[lang = "start"]
 fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
     use mem;
-    start(argc, argv, proc() {
+    start(argc, argv, Thunk::new(move|| {
         let main: extern "Rust" fn() = unsafe { mem::transmute(main) };
         main();
-    })
+    }))
 }
 
 /// Executes the given procedure after initializing the runtime with the given
@@ -102,7 +103,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
 ///
 /// This function will only return once *all* native threads in the system have
 /// exited.
-pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
+pub fn start(argc: int, argv: *const *const u8, main: Thunk) -> int {
     use prelude::*;
     use rt;
     use rustrt::task::Task;
@@ -144,7 +145,7 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
         unsafe {
             rustrt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
         }
-        (main.take().unwrap())();
+        (main.take().unwrap()).invoke(());
         exit_code = Some(os::get_exit_status());
     }).destroy());
     unsafe { rt::cleanup(); }
diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs
index a8c9983e5aa..e5a1e09967c 100644
--- a/src/libstd/sync/future.rs
+++ b/src/libstd/sync/future.rs
@@ -17,7 +17,7 @@
 //! use std::sync::Future;
 //! # fn fib(n: uint) -> uint {42};
 //! # fn make_a_sandwich() {};
-//! let mut delayed_fib = Future::spawn(proc() { fib(5000) });
+//! let mut delayed_fib = Future::spawn(move|| { fib(5000) });
 //! make_a_sandwich();
 //! println!("fib(5000) = {}", delayed_fib.get())
 //! ```
@@ -30,6 +30,7 @@ use core::mem::replace;
 use self::FutureState::*;
 use comm::{Receiver, channel};
 use task::spawn;
+use thunk::{Thunk};
 
 /// A type encapsulating the result of a computation which may not be complete
 pub struct Future<A> {
@@ -37,7 +38,7 @@ pub struct Future<A> {
 }
 
 enum FutureState<A> {
-    Pending(proc():Send -> A),
+    Pending(Thunk<(),A>),
     Evaluating,
     Forced(A)
 }
@@ -78,7 +79,7 @@ impl<A> Future<A> {
                 match replace(&mut self.state, Evaluating) {
                     Forced(_) | Evaluating => panic!("Logic error."),
                     Pending(f) => {
-                        self.state = Forced(f());
+                        self.state = Forced(f.invoke(()));
                         self.get_ref()
                     }
                 }
@@ -97,7 +98,9 @@ impl<A> Future<A> {
         Future {state: Forced(val)}
     }
 
-    pub fn from_fn(f: proc():Send -> A) -> Future<A> {
+    pub fn from_fn<F>(f: F) -> Future<A>
+        where F : FnOnce() -> A, F : Send
+    {
         /*!
          * Create a future from a function.
          *
@@ -106,7 +109,7 @@ impl<A> Future<A> {
          * function. It is not spawned into another task.
          */
 
-        Future {state: Pending(f)}
+        Future {state: Pending(Thunk::new(f))}
     }
 }
 
@@ -119,12 +122,14 @@ impl<A:Send> Future<A> {
          * waiting for the result to be received on the port.
          */
 
-        Future::from_fn(proc() {
+        Future::from_fn(move|:| {
             rx.recv()
         })
     }
 
-    pub fn spawn(blk: proc():Send -> A) -> Future<A> {
+    pub fn spawn<F>(blk: F) -> Future<A>
+        where F : FnOnce() -> A, F : Send
+    {
         /*!
          * Create a future from a unique closure.
          *
@@ -134,7 +139,7 @@ impl<A:Send> Future<A> {
 
         let (tx, rx) = channel();
 
-        spawn(proc() {
+        spawn(move |:| {
             // Don't panic if the other end has hung up
             let _ = tx.send_opt(blk());
         });
@@ -166,7 +171,7 @@ mod test {
 
     #[test]
     fn test_from_fn() {
-        let mut f = Future::from_fn(proc() "brail".to_string());
+        let mut f = Future::from_fn(move|| "brail".to_string());
         assert_eq!(f.get(), "brail");
     }
 
@@ -190,14 +195,14 @@ mod test {
 
     #[test]
     fn test_spawn() {
-        let mut f = Future::spawn(proc() "bale".to_string());
+        let mut f = Future::spawn(move|| "bale".to_string());
         assert_eq!(f.get(), "bale");
     }
 
     #[test]
     #[should_fail]
     fn test_future_panic() {
-        let mut f = Future::spawn(proc() panic!());
+        let mut f = Future::spawn(move|| panic!());
         let _x: String = f.get();
     }
 
@@ -205,8 +210,8 @@ mod test {
     fn test_sendable_future() {
         let expected = "schlorf";
         let (tx, rx) = channel();
-        let f = Future::spawn(proc() { expected });
-        task::spawn(proc() {
+        let f = Future::spawn(move|| { expected });
+        task::spawn(move|| {
             let mut f = f;
             tx.send(f.get());
         });
diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs
index 4ae5cd054f6..a684c6502ae 100644
--- a/src/libstd/sync/task_pool.rs
+++ b/src/libstd/sync/task_pool.rs
@@ -72,7 +72,7 @@ pub struct TaskPool {
     //
     // This is the only such Sender, so when it is dropped all subtasks will
     // quit.
-    jobs: Sender<proc(): Send>
+    jobs: Sender<Thunk>
 }
 
 impl TaskPool {
@@ -84,7 +84,7 @@ impl TaskPool {
     pub fn new(tasks: uint) -> TaskPool {
         assert!(tasks >= 1);
 
-        let (tx, rx) = channel::<proc(): Send>();
+        let (tx, rx) = channel::<Thunk>();
         let rx = Arc::new(Mutex::new(rx));
 
         // Taskpool tasks.
@@ -96,13 +96,15 @@ impl TaskPool {
     }
 
     /// Executes the function `job` on a task in the pool.
-    pub fn execute(&self, job: proc():Send) {
-        self.jobs.send(job);
+    pub fn execute<F>(&self, job: F)
+        where F : FnOnce(), F : Send
+    {
+        self.jobs.send(Thunk::new(job));
     }
 }
 
-fn spawn_in_pool(jobs: Arc<Mutex<Receiver<proc(): Send>>>) {
-    spawn(proc() {
+fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
+    spawn(move |:| {
         // Will spawn a new task on panic unless it is cancelled.
         let sentinel = Sentinel::new(&jobs);
 
@@ -115,7 +117,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<proc(): Send>>>) {
             };
 
             match message {
-                Ok(job) => job(),
+                Ok(job) => job.invoke(()),
 
                 // The Taskpool was dropped.
                 Err(..) => break
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index dfbba0f335c..f71b34304ab 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -531,8 +531,11 @@ impl Process {
     }
 }
 
-fn with_argv<T>(prog: &CString, args: &[CString],
-                cb: proc(*const *const libc::c_char) -> T) -> T {
+fn with_argv<T,F>(prog: &CString, args: &[CString],
+                  cb: F)
+                  -> T
+    where F : FnOnce(*const *const libc::c_char) -> T
+{
     let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len()+1);
 
     // Convert the CStrings into an array of pointers. Note: the
@@ -549,9 +552,12 @@ fn with_argv<T>(prog: &CString, args: &[CString],
     cb(ptrs.as_ptr())
 }
 
-fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
-                      cb: proc(*const c_void) -> T) -> T
-    where K: BytesContainer + Eq + Hash, V: BytesContainer
+fn with_envp<K,V,T,F>(env: Option<&collections::HashMap<K, V>>,
+                      cb: F)
+                      -> T
+    where F : FnOnce(*const c_void) -> T,
+          K : BytesContainer + Eq + Hash,
+          V : BytesContainer
 {
     // On posixy systems we can pass a char** for envp, which is a
     // null-terminated array of "k=v\0" strings. Since we must create
diff --git a/src/libstd/task.rs b/src/libstd/task.rs
index 5a1a5b4fb7a..340e283708a 100644
--- a/src/libstd/task.rs
+++ b/src/libstd/task.rs
@@ -35,7 +35,7 @@
 //! ## Example
 //!
 //! ```rust
-//! spawn(proc() {
+//! spawn(move|| {
 //!     println!("Hello, World!");
 //! })
 //! ```
@@ -47,6 +47,7 @@ use any::Any;
 use borrow::IntoCow;
 use boxed::Box;
 use comm::channel;
+use core::ops::FnOnce;
 use io::{Writer, stdio};
 use kinds::{Send, marker};
 use option::Option;
@@ -57,6 +58,7 @@ use rustrt::task::Task;
 use rustrt::task;
 use str::SendStr;
 use string::{String, ToString};
+use thunk::{Thunk};
 use sync::Future;
 
 /// The task builder type.
@@ -80,7 +82,7 @@ pub struct TaskBuilder {
     // Task-local stderr
     stderr: Option<Box<Writer + Send>>,
     // Optionally wrap the eventual task body
-    gen_body: Option<proc(v: proc():Send):Send -> proc():Send>,
+    gen_body: Option<Thunk<Thunk, Thunk>>,
     nocopy: marker::NoCopy,
 }
 
@@ -129,41 +131,46 @@ impl TaskBuilder {
     }
 
     // Where spawning actually happens (whether yielding a future or not)
-    fn spawn_internal(self, f: proc():Send,
-                      on_exit: Option<proc(Result<(), Box<Any + Send>>):Send>) {
+    fn spawn_internal(
+        self,
+        f: Thunk,
+        on_exit: Option<Thunk<task::Result>>)
+    {
         let TaskBuilder {
             name, stack_size, stdout, stderr, mut gen_body, nocopy: _
         } = self;
+
         let f = match gen_body.take() {
-            Some(gen) => gen(f),
+            Some(gen) => gen.invoke(f),
             None => f
         };
+
         let opts = task::TaskOpts {
             on_exit: on_exit,
             name: name,
             stack_size: stack_size,
         };
         if stdout.is_some() || stderr.is_some() {
-            Task::spawn(opts, proc() {
+            Task::spawn(opts, move|:| {
                 let _ = stdout.map(stdio::set_stdout);
                 let _ = stderr.map(stdio::set_stderr);
-                f();
-            })
+                f.invoke(());
+            });
         } else {
-            Task::spawn(opts, f)
+            Task::spawn(opts, move|:| f.invoke(()))
         }
     }
 
     /// Creates and executes a new child task.
     ///
     /// Sets up a new task with its own call stack and schedules it to run
-    /// the provided proc. The task has the properties and behavior
+    /// the provided function. The task has the properties and behavior
     /// specified by the `TaskBuilder`.
-    pub fn spawn(self, f: proc():Send) {
-        self.spawn_internal(f, None)
+    pub fn spawn<F:FnOnce()+Send>(self, f: F) {
+        self.spawn_internal(Thunk::new(f), None)
     }
 
-    /// Execute a proc in a newly-spawned task and return a future representing
+    /// Execute a function in a newly-spawned task and return a future representing
     /// the task's result. The task has the properties and behavior
     /// specified by the `TaskBuilder`.
     ///
@@ -178,20 +185,22 @@ impl TaskBuilder {
     /// `result::Result::Err` containing the argument to `panic!(...)` as an
     /// `Any` trait object.
     #[experimental = "Futures are experimental."]
-    pub fn try_future<T:Send>(self, f: proc():Send -> T)
-                              -> Future<Result<T, Box<Any + Send>>> {
-        // currently, the on_exit proc provided by librustrt only works for unit
+    pub fn try_future<T:Send,F:FnOnce()->(T)+Send>(self, f: F)
+                                                   -> Future<Result<T, Box<Any + Send>>> {
+        // currently, the on_exit fn provided by librustrt only works for unit
         // results, so we use an additional side-channel to communicate the
         // result.
 
         let (tx_done, rx_done) = channel(); // signal that task has exited
         let (tx_retv, rx_retv) = channel(); // return value from task
 
-        let on_exit = proc(res) { let _ = tx_done.send_opt(res); };
-        self.spawn_internal(proc() { let _ = tx_retv.send_opt(f()); },
+        let on_exit: Thunk<task::Result> = Thunk::with_arg(move |: res: task::Result| {
+            let _ = tx_done.send_opt(res);
+        });
+        self.spawn_internal(Thunk::new(move |:| { let _ = tx_retv.send_opt(f()); }),
                             Some(on_exit));
 
-        Future::from_fn(proc() {
+        Future::from_fn(move|:| {
             rx_done.recv().map(|_| rx_retv.recv())
         })
     }
@@ -199,7 +208,9 @@ impl TaskBuilder {
     /// Execute a function in a newly-spawnedtask and block until the task
     /// completes or panics. Equivalent to `.try_future(f).unwrap()`.
     #[unstable = "Error type may change."]
-    pub fn try<T:Send>(self, f: proc():Send -> T) -> Result<T, Box<Any + Send>> {
+    pub fn try<T,F>(self, f: F) -> Result<T, Box<Any + Send>>
+        where F : FnOnce() -> T, F : Send, T : Send
+    {
         self.try_future(f).into_inner()
     }
 }
@@ -212,7 +223,7 @@ impl TaskBuilder {
 /// the provided unique closure.
 ///
 /// This function is equivalent to `TaskBuilder::new().spawn(f)`.
-pub fn spawn(f: proc(): Send) {
+pub fn spawn<F:FnOnce()+Send>(f: F) {
     TaskBuilder::new().spawn(f)
 }
 
@@ -221,7 +232,9 @@ pub fn spawn(f: proc(): Send) {
 ///
 /// This is equivalent to `TaskBuilder::new().try`.
 #[unstable = "Error type may change."]
-pub fn try<T: Send>(f: proc(): Send -> T) -> Result<T, Box<Any + Send>> {
+pub fn try<T,F>(f: F) -> Result<T, Box<Any + Send>>
+    where T : Send, F : FnOnce() -> T, F : Send
+{
     TaskBuilder::new().try(f)
 }
 
@@ -230,11 +243,12 @@ pub fn try<T: Send>(f: proc(): Send -> T) -> Result<T, Box<Any + Send>> {
 ///
 /// This is equivalent to `TaskBuilder::new().try_future`.
 #[experimental = "Futures are experimental."]
-pub fn try_future<T:Send>(f: proc():Send -> T) -> Future<Result<T, Box<Any + Send>>> {
+pub fn try_future<T,F>(f: F) -> Future<Result<T, Box<Any + Send>>>
+    where T:Send, F:FnOnce()->T, F:Send
+{
     TaskBuilder::new().try_future(f)
 }
 
-
 /* Lifecycle functions */
 
 /// Read the name of the current task.
@@ -274,6 +288,8 @@ mod test {
     use result;
     use std::io::{ChanReader, ChanWriter};
     use string::String;
+    use thunk::Thunk;
+    use prelude::*;
     use super::*;
 
     // !!! These tests are dangerous. If something is buggy, they will hang, !!!
@@ -281,28 +297,28 @@ mod test {
 
     #[test]
     fn test_unnamed_task() {
-        try(proc() {
+        try(move|| {
             assert!(name().is_none());
         }).map_err(|_| ()).unwrap();
     }
 
     #[test]
     fn test_owned_named_task() {
-        TaskBuilder::new().named("ada lovelace".to_string()).try(proc() {
+        TaskBuilder::new().named("ada lovelace".to_string()).try(move|| {
             assert!(name().unwrap() == "ada lovelace");
         }).map_err(|_| ()).unwrap();
     }
 
     #[test]
     fn test_static_named_task() {
-        TaskBuilder::new().named("ada lovelace").try(proc() {
+        TaskBuilder::new().named("ada lovelace").try(move|| {
             assert!(name().unwrap() == "ada lovelace");
         }).map_err(|_| ()).unwrap();
     }
 
     #[test]
     fn test_send_named_task() {
-        TaskBuilder::new().named("ada lovelace".into_cow()).try(proc() {
+        TaskBuilder::new().named("ada lovelace".into_cow()).try(move|| {
             assert!(name().unwrap() == "ada lovelace");
         }).map_err(|_| ()).unwrap();
     }
@@ -310,7 +326,7 @@ mod test {
     #[test]
     fn test_run_basic() {
         let (tx, rx) = channel();
-        TaskBuilder::new().spawn(proc() {
+        TaskBuilder::new().spawn(move|| {
             tx.send(());
         });
         rx.recv();
@@ -318,10 +334,10 @@ mod test {
 
     #[test]
     fn test_try_future() {
-        let result = TaskBuilder::new().try_future(proc() {});
+        let result = TaskBuilder::new().try_future(move|| {});
         assert!(result.unwrap().is_ok());
 
-        let result = TaskBuilder::new().try_future(proc() -> () {
+        let result = TaskBuilder::new().try_future(move|| -> () {
             panic!();
         });
         assert!(result.unwrap().is_err());
@@ -329,7 +345,7 @@ mod test {
 
     #[test]
     fn test_try_success() {
-        match try(proc() {
+        match try(move|| {
             "Success!".to_string()
         }).as_ref().map(|s| s.as_slice()) {
             result::Result::Ok("Success!") => (),
@@ -339,7 +355,7 @@ mod test {
 
     #[test]
     fn test_try_panic() {
-        match try(proc() {
+        match try(move|| {
             panic!()
         }) {
             result::Result::Err(_) => (),
@@ -355,7 +371,7 @@ mod test {
 
         fn f(i: int, tx: Sender<()>) {
             let tx = tx.clone();
-            spawn(proc() {
+            spawn(move|| {
                 if i == 0 {
                     tx.send(());
                 } else {
@@ -372,8 +388,8 @@ mod test {
     fn test_spawn_sched_childs_on_default_sched() {
         let (tx, rx) = channel();
 
-        spawn(proc() {
-            spawn(proc() {
+        spawn(move|| {
+            spawn(move|| {
                 tx.send(());
             });
         });
@@ -382,17 +398,17 @@ mod test {
     }
 
     fn avoid_copying_the_body<F>(spawnfn: F) where
-        F: FnOnce(proc():Send),
+        F: FnOnce(Thunk),
     {
         let (tx, rx) = channel::<uint>();
 
         let x = box 1;
         let x_in_parent = (&*x) as *const int as uint;
 
-        spawnfn(proc() {
+        spawnfn(Thunk::new(move|| {
             let x_in_child = (&*x) as *const int as uint;
             tx.send(x_in_child);
-        });
+        }));
 
         let x_in_child = rx.recv();
         assert_eq!(x_in_parent, x_in_child);
@@ -400,25 +416,21 @@ mod test {
 
     #[test]
     fn test_avoid_copying_the_body_spawn() {
-        avoid_copying_the_body(spawn);
+        avoid_copying_the_body(|t| spawn(move|| t.invoke(())));
     }
 
     #[test]
     fn test_avoid_copying_the_body_task_spawn() {
         avoid_copying_the_body(|f| {
             let builder = TaskBuilder::new();
-            builder.spawn(proc() {
-                f();
-            });
+            builder.spawn(move|| f.invoke(()));
         })
     }
 
     #[test]
     fn test_avoid_copying_the_body_try() {
         avoid_copying_the_body(|f| {
-            let _ = try(proc() {
-                f()
-            });
+            let _ = try(move|| f.invoke(()));
         })
     }
 
@@ -429,24 +441,24 @@ mod test {
         // (well, it would if the constant were 8000+ - I lowered it to be more
         // valgrind-friendly. try this at home, instead..!)
         static GENERATIONS: uint = 16;
-        fn child_no(x: uint) -> proc(): Send {
-            return proc() {
+        fn child_no(x: uint) -> Thunk {
+            return Thunk::new(move|| {
                 if x < GENERATIONS {
-                    TaskBuilder::new().spawn(child_no(x+1));
+                    TaskBuilder::new().spawn(move|| child_no(x+1).invoke(()));
                 }
-            }
+            });
         }
-        TaskBuilder::new().spawn(child_no(0));
+        TaskBuilder::new().spawn(|| child_no(0).invoke(()));
     }
 
     #[test]
     fn test_simple_newsched_spawn() {
-        spawn(proc()())
+        spawn(move|| ())
     }
 
     #[test]
     fn test_try_panic_message_static_str() {
-        match try(proc() {
+        match try(move|| {
             panic!("static string");
         }) {
             Err(e) => {
@@ -460,7 +472,7 @@ mod test {
 
     #[test]
     fn test_try_panic_message_owned_str() {
-        match try(proc() {
+        match try(move|| {
             panic!("owned string".to_string());
         }) {
             Err(e) => {
@@ -474,7 +486,7 @@ mod test {
 
     #[test]
     fn test_try_panic_message_any() {
-        match try(proc() {
+        match try(move|| {
             panic!(box 413u16 as Box<Any + Send>);
         }) {
             Err(e) => {
@@ -492,7 +504,7 @@ mod test {
     fn test_try_panic_message_unit_struct() {
         struct Juju;
 
-        match try(proc() {
+        match try(move|| {
             panic!(Juju)
         }) {
             Err(ref e) if e.is::<Juju>() => {}
@@ -507,7 +519,7 @@ mod test {
         let stdout = ChanWriter::new(tx);
 
         let r = TaskBuilder::new().stdout(box stdout as Box<Writer + Send>)
-                                  .try(proc() {
+                                  .try(move|| {
                 print!("Hello, world!");
             });
         assert!(r.is_ok());
@@ -527,7 +539,7 @@ fn task_abort_no_kill_runtime() {
     use mem;
 
     let tb = TaskBuilder::new();
-    let rx = tb.try_future(proc() {});
+    let rx = tb.try_future(move|| {});
     mem::drop(rx);
     timer::sleep(Duration::milliseconds(1000));
 }