]> git.lizzy.rs Git - rust.git/blobdiff - src/libnative/task.rs
auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis
[rust.git] / src / libnative / task.rs
index b073c2c7fbf026f8ecfe52b3a1065279315c3bb7..c72d6c24a7c16ffa5b6cd661c9b8d2698322323c 100644 (file)
@@ -27,6 +27,7 @@
 
 use io;
 use task;
+use std::task::{TaskBuilder, Spawner};
 
 /// Creates a new Task which is ready to execute as a 1:1 task.
 pub fn new(stack_bounds: (uint, uint)) -> Box<Task> {
@@ -48,12 +49,14 @@ fn ops() -> Box<Ops> {
 }
 
 /// Spawns a function with the default configuration
+#[deprecated = "use the native method of NativeTaskBuilder instead"]
 pub fn spawn(f: proc():Send) {
     spawn_opts(TaskOpts { name: None, stack_size: None, on_exit: None }, f)
 }
 
 /// Spawns a new task given the configuration options and a procedure to run
 /// inside the task.
+#[deprecated = "use the native method of NativeTaskBuilder instead"]
 pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
     let TaskOpts { name, stack_size, on_exit } = opts;
 
@@ -68,7 +71,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
     // Note that this increment must happen *before* the spawn in order to
     // guarantee that if this task exits it will always end up waiting for the
     // spawned task to exit.
-    bookkeeping::increment();
+    let token = bookkeeping::increment();
 
     // Spawning a new OS thread guarantees that __morestack will never get
     // triggered, but we must manually set up the actual stack bounds once this
@@ -78,7 +81,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
     // which our stack started).
     Thread::spawn_stack(stack, proc() {
         let something_around_the_top_of_the_stack = 1;
-        let addr = &something_around_the_top_of_the_stack as *int;
+        let addr = &something_around_the_top_of_the_stack as *const int;
         let my_stack = addr as uint;
         unsafe {
             stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
@@ -89,12 +92,31 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
         let mut f = Some(f);
         let mut task = task;
         task.put_runtime(ops);
-        let t = task.run(|| { f.take_unwrap()() });
-        drop(t);
-        bookkeeping::decrement();
+        drop(task.run(|| { f.take_unwrap()() }).destroy());
+        drop(token);
     })
 }
 
+/// A spawner for native tasks
+pub struct NativeSpawner;
+
+impl Spawner for NativeSpawner {
+    fn spawn(self, opts: TaskOpts, f: proc():Send) {
+        spawn_opts(opts, f)
+    }
+}
+
+/// An extension trait adding a `native` configuration method to `TaskBuilder`.
+pub trait NativeTaskBuilder {
+    fn native(self) -> TaskBuilder<NativeSpawner>;
+}
+
+impl<S: Spawner> NativeTaskBuilder for TaskBuilder<S> {
+    fn native(self) -> TaskBuilder<NativeSpawner> {
+        self.spawner(NativeSpawner)
+    }
+}
+
 // This structure is the glue between channels and the 1:1 scheduling mode. This
 // structure is allocated once per task.
 struct Ops {
@@ -109,21 +131,21 @@ struct Ops {
 }
 
 impl rt::Runtime for Ops {
-    fn yield_now(~self, mut cur_task: Box<Task>) {
+    fn yield_now(self: Box<Ops>, mut cur_task: Box<Task>) {
         // put the task back in TLS and then invoke the OS thread yield
         cur_task.put_runtime(self);
         Local::put(cur_task);
         Thread::yield_now();
     }
 
-    fn maybe_yield(~self, mut cur_task: Box<Task>) {
+    fn maybe_yield(self: Box<Ops>, mut cur_task: Box<Task>) {
         // just put the task back in TLS, on OS threads we never need to
         // opportunistically yield b/c the OS will do that for us (preemption)
         cur_task.put_runtime(self);
         Local::put(cur_task);
     }
 
-    fn wrap(~self) -> Box<Any> {
+    fn wrap(self: Box<Ops>) -> Box<Any> {
         self as Box<Any>
     }
 
@@ -170,13 +192,15 @@ fn can_block(&self) -> bool { true }
     // `awoken` field which indicates whether we were actually woken up via some
     // invocation of `reawaken`. This flag is only ever accessed inside the
     // lock, so there's no need to make it atomic.
-    fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
+    fn deschedule(mut self: Box<Ops>,
+                  times: uint,
+                  mut cur_task: Box<Task>,
                   f: |BlockedTask| -> Result<(), BlockedTask>) {
         let me = &mut *self as *mut Ops;
         cur_task.put_runtime(self);
 
         unsafe {
-            let cur_task_dupe = &*cur_task as *Task;
+            let cur_task_dupe = &mut *cur_task as *mut Task;
             let task = BlockedTask::block(cur_task);
 
             if times == 1 {
@@ -228,7 +252,7 @@ fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
 
     // See the comments on `deschedule` for why the task is forgotten here, and
     // why it's valid to do so.
-    fn reawaken(mut ~self, mut to_wake: Box<Task>) {
+    fn reawaken(mut self: Box<Ops>, mut to_wake: Box<Task>) {
         unsafe {
             let me = &mut *self as *mut Ops;
             to_wake.put_runtime(self);
@@ -239,7 +263,7 @@ fn reawaken(mut ~self, mut to_wake: Box<Task>) {
         }
     }
 
-    fn spawn_sibling(~self,
+    fn spawn_sibling(self: Box<Ops>,
                      mut cur_task: Box<Task>,
                      opts: TaskOpts,
                      f: proc():Send) {
@@ -259,7 +283,8 @@ mod tests {
     use std::rt::local::Local;
     use std::rt::task::{Task, TaskOpts};
     use std::task;
-    use super::{spawn, spawn_opts, Ops};
+    use std::task::TaskBuilder;
+    use super::{spawn, spawn_opts, Ops, NativeTaskBuilder};
 
     #[test]
     fn smoke() {
@@ -304,7 +329,7 @@ fn smoke_opts_fail() {
     fn yield_test() {
         let (tx, rx) = channel();
         spawn(proc() {
-            for _ in range(0, 10) { task::deschedule(); }
+            for _ in range(0u, 10) { task::deschedule(); }
             tx.send(());
         });
         rx.recv();
@@ -347,4 +372,12 @@ fn spawn_inherits() {
         });
         rx.recv();
     }
+
+    #[test]
+    fn test_native_builder() {
+        let res = TaskBuilder::new().native().try(proc() {
+            "Success!".to_string()
+        });
+        assert_eq!(res.ok().unwrap(), "Success!".to_string());
+    }
 }