about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libgreen/basic.rs52
-rw-r--r--src/libgreen/lib.rs2
-rw-r--r--src/libgreen/sched.rs2
3 files changed, 20 insertions, 36 deletions
diff --git a/src/libgreen/basic.rs b/src/libgreen/basic.rs
index 9e42e2f67c4..1ebebbe555e 100644
--- a/src/libgreen/basic.rs
+++ b/src/libgreen/basic.rs
@@ -15,6 +15,8 @@
 //! This implementation is also used as the fallback implementation of an event
 //! loop if no other one is provided (and M:N scheduling is desired).
 
+use alloc::arc::Arc;
+use std::sync::atomics;
 use std::mem;
 use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback};
 use std::rt::rtio::{PausableIdleCallback, Callback};
@@ -27,10 +29,11 @@ pub fn event_loop() -> Box<EventLoop:Send> {
 
 struct BasicLoop {
     work: Vec<proc():Send>,             // pending work
-    idle: Option<*mut BasicPausable>, // only one is allowed
     remotes: Vec<(uint, Box<Callback:Send>)>,
     next_remote: uint,
     messages: Exclusive<Vec<Message>>,
+    idle: Option<Box<Callback:Send>>,
+    idle_active: Option<Arc<atomics::AtomicBool>>,
 }
 
 enum Message { RunRemote(uint), RemoveRemote(uint) }
@@ -40,6 +43,7 @@ impl BasicLoop {
         BasicLoop {
             work: vec![],
             idle: None,
+            idle_active: None,
             next_remote: 0,
             remotes: vec![],
             messages: Exclusive::new(vec![]),
@@ -92,20 +96,18 @@ impl BasicLoop {
 
     /// Run the idle callback if one is registered
     fn idle(&mut self) {
-        unsafe {
-            match self.idle {
-                Some(idle) => {
-                    if (*idle).active {
-                        (*idle).work.call();
-                    }
+        match self.idle {
+            Some(ref mut idle) => {
+                if self.idle_active.get_ref().load(atomics::SeqCst) {
+                    idle.call();
                 }
-                None => {}
             }
+            None => {}
         }
     }
 
     fn has_idle(&self) -> bool {
-        unsafe { self.idle.is_some() && (**self.idle.get_ref()).active }
+        self.idle.is_some() && self.idle_active.get_ref().load(atomics::SeqCst)
     }
 }
 
@@ -141,13 +143,11 @@ impl EventLoop for BasicLoop {
     // FIXME: Seems like a really weird requirement to have an event loop provide.
     fn pausable_idle_callback(&mut self, cb: Box<Callback:Send>)
                               -> Box<PausableIdleCallback:Send> {
-        let callback = box BasicPausable::new(self, cb);
         rtassert!(self.idle.is_none());
-        unsafe {
-            let cb_ptr: &*mut BasicPausable = mem::transmute(&callback);
-            self.idle = Some(*cb_ptr);
-        }
-        callback as Box<PausableIdleCallback:Send>
+        self.idle = Some(cb);
+        let a = Arc::new(atomics::AtomicBool::new(true));
+        self.idle_active = Some(a.clone());
+        box BasicPausable { active: a } as Box<PausableIdleCallback:Send>
     }
 
     fn remote_callback(&mut self, f: Box<Callback:Send>)
@@ -196,35 +196,21 @@ impl Drop for BasicRemote {
 }
 
 struct BasicPausable {
-    eloop: *mut BasicLoop,
-    work: Box<Callback:Send>,
-    active: bool,
-}
-
-impl BasicPausable {
-    fn new(eloop: &mut BasicLoop, cb: Box<Callback:Send>) -> BasicPausable {
-        BasicPausable {
-            active: false,
-            work: cb,
-            eloop: eloop,
-        }
-    }
+    active: Arc<atomics::AtomicBool>,
 }
 
 impl PausableIdleCallback for BasicPausable {
     fn pause(&mut self) {
-        self.active = false;
+        self.active.store(false, atomics::SeqCst);
     }
     fn resume(&mut self) {
-        self.active = true;
+        self.active.store(true, atomics::SeqCst);
     }
 }
 
 impl Drop for BasicPausable {
     fn drop(&mut self) {
-        unsafe {
-            (*self.eloop).idle = None;
-        }
+        self.active.store(false, atomics::SeqCst);
     }
 }
 
diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs
index 53e2574df59..39b64857163 100644
--- a/src/libgreen/lib.rs
+++ b/src/libgreen/lib.rs
@@ -435,7 +435,6 @@ impl SchedPool {
                                             pool.sleepers.clone(),
                                             pool.task_state.clone());
             pool.handles.push(sched.make_handle());
-            let sched = sched;
             pool.threads.push(Thread::start(proc() { sched.bootstrap(); }));
         }
 
@@ -497,7 +496,6 @@ impl SchedPool {
                                         self.task_state.clone());
         let ret = sched.make_handle();
         self.handles.push(sched.make_handle());
-        let sched = sched;
         self.threads.push(Thread::start(proc() { sched.bootstrap() }));
 
         return ret;
diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs
index 7faa9207bbb..d28e74a2b80 100644
--- a/src/libgreen/sched.rs
+++ b/src/libgreen/sched.rs
@@ -1142,7 +1142,7 @@ mod test {
 
         Thread::start(proc() {
             let sleepers = SleeperList::new();
-            let mut pool = BufferPool::new();
+            let pool = BufferPool::new();
             let (normal_worker, normal_stealer) = pool.deque();
             let (special_worker, special_stealer) = pool.deque();
             let queues = vec![normal_stealer, special_stealer];