green: Remove some unsafe code in BasicLoop

This commit is contained in:
Alex Crichton 2014-05-20 18:51:29 -07:00
parent 05a453edb3
commit 54f6eacf34
3 changed files with 20 additions and 36 deletions

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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];