diff options
Diffstat (limited to 'src/libstd/sys/common/helper_thread.rs')
| -rw-r--r-- | src/libstd/sys/common/helper_thread.rs | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs index 9ef1c33312f..7093c417b11 100644 --- a/src/libstd/sys/common/helper_thread.rs +++ b/src/libstd/sys/common/helper_thread.rs @@ -20,6 +20,8 @@ //! can be created in the future and there must be no active timers at that //! time. +#![macro_escape] + use prelude::*; use cell::UnsafeCell; @@ -68,6 +70,17 @@ struct RaceBox(helper_signal::signal); unsafe impl Send for RaceBox {} unsafe impl Sync for RaceBox {} +macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( + static $name: Helper<$m> = Helper { + lock: ::sync::MUTEX_INIT, + cond: ::sync::CONDVAR_INIT, + chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> }, + signal: ::cell::UnsafeCell { value: 0 }, + initialized: ::cell::UnsafeCell { value: false }, + shutdown: ::cell::UnsafeCell { value: false }, + }; +) } + impl<M: Send> Helper<M> { /// Lazily boots a helper thread, becoming a no-op if the helper has already /// been spawned. @@ -84,7 +97,7 @@ impl<M: Send> Helper<M> { { unsafe { let _guard = self.lock.lock().unwrap(); - if !*self.initialized.get() { + if *self.chan.get() as uint == 0 { let (tx, rx) = channel(); *self.chan.get() = mem::transmute(box tx); let (receive, send) = helper_signal::new(); @@ -93,15 +106,17 @@ impl<M: Send> Helper<M> { let receive = RaceBox(receive); let t = f(); - Thread::spawn(move |:| { + Thread::spawn(move || { helper(receive.0, rx, t); let _g = self.lock.lock().unwrap(); *self.shutdown.get() = true; self.cond.notify_one() }).detach(); - rt::at_exit(move|:| { self.shutdown() }); + rt::at_exit(move || { self.shutdown() }); *self.initialized.get() = true; + } else if *self.chan.get() as uint == 1 { + panic!("cannot continue usage after shutdown"); } } } @@ -116,7 +131,9 @@ impl<M: Send> Helper<M> { // Must send and *then* signal to ensure that the child receives the // message. Otherwise it could wake up and go to sleep before we // send the message. - assert!(!self.chan.get().is_null()); + assert!(*self.chan.get() as uint != 0); + assert!(*self.chan.get() as uint != 1, + "cannot continue usage after shutdown"); (**self.chan.get()).send(msg); helper_signal::signal(*self.signal.get() as helper_signal::signal); } @@ -129,9 +146,13 @@ impl<M: Send> Helper<M> { // returns. let mut guard = self.lock.lock().unwrap(); + let ptr = *self.chan.get(); + if ptr as uint == 1 { + panic!("cannot continue usage after shutdown"); + } // Close the channel by destroying it let chan: Box<Sender<M>> = mem::transmute(*self.chan.get()); - *self.chan.get() = 0 as *mut Sender<M>; + *self.chan.get() = 1 as *mut Sender<M>; drop(chan); helper_signal::signal(*self.signal.get() as helper_signal::signal); |
