about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorEric Reed <ecreed@cs.washington.edu>2013-08-27 09:57:30 -0700
committerEric Reed <ecreed@cs.washington.edu>2013-08-27 14:28:34 -0700
commitefb8924f8848f39811a8e69db182effb465ad3cf (patch)
treee612a673a54e6131468aa9eec5ced8e27fe09d34 /src/libstd/rt
parented422b88727807aee40495a6193a69e4c3842be1 (diff)
downloadrust-efb8924f8848f39811a8e69db182effb465ad3cf.tar.gz
rust-efb8924f8848f39811a8e69db182effb465ad3cf.zip
Add a variant of home_for_io that consumes the handle. Refactor out common parts of the home_for_io variants.
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/uv/uvio.rs101
1 files changed, 53 insertions, 48 deletions
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index f282432dcb5..ad9d2a59794 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -26,6 +26,7 @@ use rt::local::Local;
 use rt::rtio::*;
 use rt::sched::{Scheduler, SchedHandle};
 use rt::tube::Tube;
+use rt::task::SchedHome;
 use rt::uv::*;
 use rt::uv::idle::IdleWatcher;
 use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
@@ -47,76 +48,80 @@ use task;
 // XXX we should not be calling uvll functions in here.
 
 trait HomingIO {
+
     fn home<'r>(&'r mut self) -> &'r mut SchedHandle;
+
     /* XXX This will move pinned tasks to do IO on the proper scheduler
      * and then move them back to their home.
      */
-    fn home_for_io<A>(&mut self, io: &fn(&mut Self) -> A) -> A {
-        use rt::sched::{PinnedTask, TaskFromFriend};
-        // go home
-        let old_home = Cell::new_empty();
-        let old_home_ptr = &old_home;
+    fn go_to_IO_home(&mut self) -> SchedHome {
+        use rt::sched::PinnedTask;
+
         do task::unkillable { // FIXME(#8674)
-            let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                // get the old home first
-                do task.wake().map_move |mut task| {
-                    old_home_ptr.put_back(task.take_unwrap_home());
-                    self.home().send(PinnedTask(task));
-                };
+            let mut old = None;
+            {
+                let ptr = &mut old;
+                let scheduler: ~Scheduler = Local::take();
+                do scheduler.deschedule_running_task_and_then |_, task| {
+                    /* FIXME(#8674) if the task was already killed then wake
+                     * will return None. In that case, the home pointer will never be set.
+                     *
+                     * RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
+                     */
+                    do task.wake().map_move |mut task| {
+                        *ptr = Some(task.take_unwrap_home());
+                        self.home().send(PinnedTask(task));
+                    };
+                }
             }
+            old.expect("No old home because task had already been killed.")
         }
+    }
 
-        // do IO
-        let a = io(self);
+    // XXX dummy self param
+    fn restore_original_home(_dummy_self: Option<Self>, old: SchedHome) {
+        use rt::sched::TaskFromFriend;
 
-        // unhome home
+        let old = Cell::new(old);
         do task::unkillable { // FIXME(#8674)
             let scheduler: ~Scheduler = Local::take();
             do scheduler.deschedule_running_task_and_then |scheduler, task| {
+                /* FIXME(#8674) if the task was already killed then wake
+                 * will return None. In that case, the home pointer will never be restored.
+                 *
+                 * RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
+                 */
                 do task.wake().map_move |mut task| {
-                    task.give_home(old_home.take());
+                    task.give_home(old.take());
                     scheduler.make_handle().send(TaskFromFriend(task));
                 };
             }
         }
-
-        // return the result of the IO
-        a
     }
 
-    fn home_for_io_with_sched<A>(&mut self, io_sched: &fn(&mut Self, ~Scheduler) -> A) -> A {
-        use rt::sched::{PinnedTask, TaskFromFriend};
-
-        do task::unkillable { // FIXME(#8674)
-            // go home
-            let old_home = Cell::new_empty();
-            let old_home_ptr = &old_home;
-            let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                // get the old home first
-                do task.wake().map_move |mut task| {
-                    old_home_ptr.put_back(task.take_unwrap_home());
-                    self.home().send(PinnedTask(task));
-                };
-            }
+    fn home_for_io<A>(&mut self, io: &fn(&mut Self) -> A) -> A {
+        let home = self.go_to_IO_home();
+        let a = io(self); // do IO
+        HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
+        a // return the result of the IO
+    }
 
-            // do IO
-            let scheduler: ~Scheduler = Local::take();
-            let a = io_sched(self, scheduler);
+    fn home_for_io_consume<A>(self, io: &fn(Self) -> A) -> A {
+        let mut this = self;
+        let home = this.go_to_IO_home();
+        let a = io(this); // do IO
+        HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
+        a // return the result of the IO
+    }
 
-            // unhome home
+    fn home_for_io_with_sched<A>(&mut self, io_sched: &fn(&mut Self, ~Scheduler) -> A) -> A {
+        let home = self.go_to_IO_home();
+        let a = do task::unkillable { // FIXME(#8674)
             let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |scheduler, task| {
-                do task.wake().map_move |mut task| {
-                    task.give_home(old_home.take());
-                    scheduler.make_handle().send(TaskFromFriend(task));
-                };
-            }
-
-            // return the result of the IO
-            a
-        }
+            io_sched(self, scheduler) // do IO and scheduling action
+        };
+        HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
+        a // return result of IO
     }
 }