about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-08-15 19:35:39 -0700
committertoddaaro <github@opprobrio.us>2013-08-16 16:37:09 -0700
commitbd382ee6434e995153302135816685cc9cc80441 (patch)
tree245fdf777c871263dc8af7df1dd4377d30a586d6 /src/libstd
parent066ca17eaae239a666579fc80fe9047aaac0599d (diff)
downloadrust-bd382ee6434e995153302135816685cc9cc80441.tar.gz
rust-bd382ee6434e995153302135816685cc9cc80441.zip
std::rt: Touch up idle logic
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/rt/sched.rs52
1 files changed, 36 insertions, 16 deletions
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 58e1676b424..c0481d06493 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -79,7 +79,7 @@ pub struct Scheduler {
     /// A fast XorShift rng for scheduler use
     rng: XorShiftRng,
     /// An IdleWatcher
-    idle_watcher: IdleWatcher,
+    idle_watcher: Option<IdleWatcher>,
     /// A flag to indicate whether or not the idle callback is active.
     idle_flag: bool
 }
@@ -128,9 +128,6 @@ impl Scheduler {
                        friend: Option<SchedHandle>)
         -> Scheduler {
 
-        let mut event_loop = event_loop;
-        let idle_watcher = IdleWatcher::new(event_loop.uvio.uv_loop());
-
         Scheduler {
             sleeper_list: sleeper_list,
             message_queue: MessageQueue::new(),
@@ -146,8 +143,8 @@ impl Scheduler {
             run_anything: run_anything,
             friend_handle: friend,
             rng: XorShiftRng::new(),
-            idle_watcher: idle_watcher,
-            idle_flag: true
+            idle_watcher: None,
+            idle_flag: false
         }
     }
 
@@ -175,9 +172,7 @@ impl Scheduler {
         // Before starting our first task, make sure the idle callback
         // is active. As we do not start in the sleep state this is
         // important.
-        do this.idle_watcher.start |_idle_watcher, _status| {
-            Scheduler::run_sched_once();
-        }
+        this.activate_idle();
 
         // Now, as far as all the scheduler state is concerned, we are
         // inside the "scheduler" context. So we can act like the
@@ -318,23 +313,43 @@ impl Scheduler {
         Local::put(sched);
     }
 
-    fn activate_idle(&mut self) {        
+    fn activate_idle(&mut self) {
+        rtdebug!("activating idle");
         if self.idle_flag {
+            rtassert!(self.idle_watcher.is_some());
             rtdebug!("idle flag already set, not reactivating idle watcher");
         } else {
             rtdebug!("idle flag was false, reactivating idle watcher");
             self.idle_flag = true;
-            self.idle_watcher.restart();
+            if self.idle_watcher.is_none() {
+                // There's no idle handle yet. Create one
+                let mut idle_watcher = IdleWatcher::new(self.event_loop.uvio.uv_loop());
+                do idle_watcher.start |_idle_watcher, _status| {
+                    Scheduler::run_sched_once();
+                }
+                self.idle_watcher = Some(idle_watcher);
+            } else {
+                self.idle_watcher.get_mut_ref().restart();
+            }
         }            
     }
 
     fn pause_idle(&mut self) {
-        if !self.idle_flag {
-            rtdebug!("idle flag false, not stopping idle watcher");
+        rtassert!(self.idle_watcher.is_some());
+        rtassert!(self.idle_flag);
+
+        rtdebug!("stopping idle watcher");
+
+        self.idle_flag = false;
+        if !self.no_sleep {
+            self.idle_watcher.get_mut_ref().stop();
         } else {
-            rtdebug!("idle flag true, stopping idle watcher");
-            self.idle_flag = false;
-            self.idle_watcher.stop();
+            rtdebug!("closing idle watcher");
+            // The scheduler is trying to exit. Destroy the idle watcher
+            // to drop the reference to the event loop.
+            let mut idle_watcher = self.idle_watcher.take_unwrap();
+            idle_watcher.stop();
+            idle_watcher.close(||());
         }
     }
 
@@ -357,10 +372,15 @@ impl Scheduler {
 
         let this = self;
 
+        rtdebug!("enqueuing task");
+
         // We push the task onto our local queue clone.
         this.work_queue.push(task);
 //        this.event_loop.callback(Scheduler::run_sched_once);
 
+        // There is definitely work to be done later. Make sure we wake up for it.
+        this.activate_idle();
+
         // We've made work available. Notify a
         // sleeping scheduler.