about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-05-23 00:04:50 -0700
committerBrian Anderson <banderson@mozilla.com>2013-05-28 16:25:35 -0700
commit3f8095e55043f35e08adba5fe5b0a2d687ebc514 (patch)
tree9ec5e2b31e47d2294e5f7d8d5e4cbcb9af8e0464
parent7f107c415f1c88b016b9da0fa9c58e6b61f82589 (diff)
core::rt: Add a very basic multi-threaded scheduling test
-rw-r--r--src/libcore/rt/sched.rs72
1 files changed, 70 insertions, 2 deletions
diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs
index 78c5da08c39..e78d50beebe 100644
--- a/src/libcore/rt/sched.rs
+++ b/src/libcore/rt/sched.rs
@@ -114,6 +114,8 @@ pub impl Scheduler {
         };
 
         fn wake_up() {
+            let sched = Local::take::<Scheduler>();
+            sched.resume_task_from_queue();
         }
     }
 
@@ -127,8 +129,8 @@ pub impl Scheduler {
         self.event_loop.callback(resume_task_from_queue);
 
         fn resume_task_from_queue() {
-            let scheduler = Local::take::<Scheduler>();
-            scheduler.resume_task_from_queue();
+            let sched = Local::take::<Scheduler>();
+            sched.resume_task_from_queue();
         }
     }
 
@@ -606,4 +608,70 @@ mod test {
             };
         }
     }
+
+    #[test]
+    fn multithreading() {
+        use clone::Clone;
+        use iter::Times;
+        use rt::work_queue::WorkQueue;
+        use rt::comm::*;
+        use container::Container;
+        use vec::OwnedVector;
+        use rt::rtio::RemoteCallback;
+
+        do run_in_bare_thread {
+            let work_queue1 = WorkQueue::new();
+            let work_queue2 = work_queue1.clone();
+
+            let loop1 = ~UvEventLoop::new();
+            let mut sched1 = ~Scheduler::new(loop1, work_queue1.clone());
+            let handle1 = sched1.make_handle();
+            let sched1_cell = Cell(sched1);
+            let handle1_cell = Cell(handle1);
+
+            let loop2 = ~UvEventLoop::new();
+            let mut sched2 = ~Scheduler::new(loop2, work_queue2.clone());
+            let handle2 = sched2.make_handle();
+            let sched2_cell = Cell(sched2);
+            let handle2_cell = Cell(handle2);
+
+            let _thread1 = do Thread::start {
+                let mut sched1 = sched1_cell.take();
+                sched1.run();
+            };
+
+            let _thread2 = do Thread::start {
+                let mut sched2 = sched2_cell.take();
+                let handle1_cell = Cell(handle1_cell.take());
+                let handle2_cell = Cell(handle2_cell.take());
+
+                let task = ~do Coroutine::new(&mut sched2.stack_pool) {
+                    // Hold handles to keep the schedulers alive
+                    let mut handle1 = handle1_cell.take();
+                    let mut handle2 = handle2_cell.take();
+
+                    let mut ports = ~[];
+                    for 10.times {
+                        let (port, chan) = oneshot();
+                        let chan_cell = Cell(chan);
+                        do spawntask_later {
+                            chan_cell.take().send(());
+                        }
+                        ports.push(port);
+
+                        // Make sure the other scheduler is awake
+                        handle1.remote.fire();
+                        handle2.remote.fire();
+                    }
+
+                    while !ports.is_empty() {
+                        ports.pop().recv();
+                    }
+                };
+
+                sched2.enqueue_task(task);
+                sched2.run();
+            };
+        }
+    }
 }