about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-08-03 23:29:21 -0700
committerBrian Anderson <banderson@mozilla.com>2013-08-04 15:11:56 -0700
commita27f339cb4480e723aa7e06070683966d026d1ae (patch)
tree69284728b4a806e428443a733a88635b1215e703 /src/libstd/rt
parentf0f7e1b3fcfed8b77516a871ae82a4aa8df07764 (diff)
downloadrust-a27f339cb4480e723aa7e06070683966d026d1ae.tar.gz
rust-a27f339cb4480e723aa7e06070683966d026d1ae.zip
std::rt: Don't allow schedulers to exit before handling all messages
Every time run_sched_once performs a 'scheduling action' it needs to guarantee
that it runs at least one more time, so enqueue another run_sched_once callback.
The primary reason it needs to do this is because not all async callbacks
are guaranteed to run, it's only guaranteed that *a* callback will run after
enqueing one - some may get dropped.

At the moment this means we wastefully create lots of callbacks to ensure that
there will *definitely* be a callback queued up to continue running the scheduler.
The logic really needs to be tightened up here.
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/sched.rs10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 18cfeade157..a5c8abc2a6c 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -172,6 +172,10 @@ impl Scheduler {
 
         rtdebug!("stopping scheduler %u", stask.sched.get_ref().sched_id());
 
+        // Should not have any messages
+        let message = stask.sched.get_mut_ref().message_queue.pop();
+        assert!(message.is_none());
+
         stask.destroyed = true;
     }
 
@@ -336,11 +340,14 @@ impl Scheduler {
         match this.message_queue.pop() {
             Some(PinnedTask(task)) => {
                 let mut task = task;
+                this.event_loop.callback(Scheduler::run_sched_once);
                 task.give_home(Sched(this.make_handle()));
                 this.resume_task_immediately(task);
                 return None;
             }
             Some(TaskFromFriend(task)) => {
+                this.event_loop.callback(Scheduler::run_sched_once);
+                rtdebug!("got a task from a friend. lovely!");
                 return this.sched_schedule_task(task);
             }
             Some(Wake) => {
@@ -395,6 +402,7 @@ impl Scheduler {
     /// Take a non-homed task we aren't allowed to run here and send
     /// it to the designated friend scheduler to execute.
     fn send_to_friend(&mut self, task: ~Task) {
+        rtdebug!("sending a task to friend");
         match self.friend_handle {
             Some(ref mut handle) => {
                 handle.send(TaskFromFriend(task));
@@ -426,12 +434,14 @@ impl Scheduler {
                             Scheduler::send_task_home(task);
                             return Some(this);
                         } else {
+                            this.event_loop.callback(Scheduler::run_sched_once);
                             task.give_home(Sched(home_handle));
                             this.resume_task_immediately(task);
                             return None;
                         }
                     }
                     AnySched if this.run_anything => {
+                        this.event_loop.callback(Scheduler::run_sched_once);
                         task.give_home(AnySched);
                         this.resume_task_immediately(task);
                         return None;