From 54f6eacf34c1ec368750051832aba2735fbf0880 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 May 2014 18:51:29 -0700 Subject: [PATCH] green: Remove some unsafe code in BasicLoop --- src/libgreen/basic.rs | 52 ++++++++++++++++--------------------------- src/libgreen/lib.rs | 2 -- src/libgreen/sched.rs | 2 +- 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 { struct BasicLoop { work: Vec, // pending work - idle: Option<*mut BasicPausable>, // only one is allowed remotes: Vec<(uint, Box)>, next_remote: uint, messages: Exclusive>, + idle: Option>, + idle_active: Option>, } 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) -> Box { - 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 + self.idle = Some(cb); + let a = Arc::new(atomics::AtomicBool::new(true)); + self.idle_active = Some(a.clone()); + box BasicPausable { active: a } as Box } fn remote_callback(&mut self, f: Box) @@ -196,35 +196,21 @@ impl Drop for BasicRemote { } struct BasicPausable { - eloop: *mut BasicLoop, - work: Box, - active: bool, -} - -impl BasicPausable { - fn new(eloop: &mut BasicLoop, cb: Box) -> BasicPausable { - BasicPausable { - active: false, - work: cb, - eloop: eloop, - } - } + active: Arc, } 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];