Commit 48f64dce authored by Ralf's avatar Ralf
Browse files

implement waking up a thread

parent 9058fa27
// While we are still prototyping, allow dead code // FIXME: While we are still prototyping, allow dead code
#![allow(dead_code)] #![allow(dead_code)]
#[macro_use] #[macro_use]
......
use std::time::Duration; use std::time::Duration;
use std::sync; use std::sync::{Arc, Mutex, Condvar};
use std::thread; use std::thread;
#[derive(PartialEq,Eq,Debug,Copy,Clone)]
pub enum ShouldThreadRun {
Yes,
No,
}
pub struct Wakeable<T> { pub struct Wakeable<T> {
join: thread::JoinHandle<T>, join: thread::JoinHandle<T>,
state: Arc<ThreadState>,
}
pub struct Thread {
state: Arc<ThreadState>,
}
struct ThreadState {
mutex: Mutex<ShouldThreadRun>,
cond: Condvar,
} }
pub struct Thread;
impl<T: Send + 'static> Wakeable<T> { impl<T: Send + 'static> Wakeable<T> {
pub fn new<F>(f: F) -> Self pub fn new<F>(f: F) -> Self
where F: FnOnce(Thread) -> T + Send + 'static where F: FnOnce(Thread) -> T + Send + 'static
{ {
Wakeable { join: thread::spawn(|| f(Thread)) } let state = Arc::new(ThreadState {
mutex: Mutex::new(ShouldThreadRun::Yes),
cond: Condvar::new(),
});
let thread = Thread { state: state.clone() };
Wakeable {
join: thread::spawn(move || f(thread)),
state: state,
}
} }
pub fn terminate(self) -> T { pub fn terminate(self) -> T {
{
// We panic if the lock is poisened, which only happens if someone paniced
let mut should_run = self.state.mutex.lock().unwrap();
*should_run = ShouldThreadRun::No;
self.state.cond.notify_one();
}
self.join.join().unwrap() // If the child thread paniced, so do we self.join.join().unwrap() // If the child thread paniced, so do we
} }
} }
impl Thread { impl Thread {
pub fn sleep(&self, _: Duration) -> sync::WaitTimeoutResult { pub fn sleep(&self, d: Duration) -> ShouldThreadRun {
unimplemented!() // We panic if the lock is poisened, which only happens if someone paniced
let should_run = self.state.mutex.lock().unwrap();
// check if we have to terminate early
if *should_run == ShouldThreadRun::No {
return ShouldThreadRun::No;
}
// We panic if the lock is poisened, which only happens if someone paniced
let (should_run, _) = self.state.cond.wait_timeout(should_run, d).unwrap();
return *should_run;
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment