use std::sync::{Mutex, MutexGuard, Condvar};
use std::cell::Cell;
use std::time::Instant;
pub struct ThreadParker {
should_park: Cell<bool>,
mutex: Mutex<()>,
condvar: Condvar,
}
impl ThreadParker {
pub fn new() -> ThreadParker {
ThreadParker {
should_park: Cell::new(false),
mutex: Mutex::new(()),
condvar: Condvar::new(),
}
}
pub fn prepare_park(&self) {
self.should_park.set(true);
}
pub fn timed_out(&self) -> bool {
self.should_park.get()
}
pub fn park(&self) {
let mut lock = self.mutex.lock().unwrap();
while self.should_park.get() {
lock = self.condvar.wait(lock).unwrap();
}
}
pub fn park_until(&self, timeout: Instant) -> bool {
let mut lock = self.mutex.lock().unwrap();
while self.should_park.get() {
let now = Instant::now();
if timeout <= now {
return false;
}
let (new_lock, _) = self.condvar.wait_timeout(lock, timeout - now).unwrap();
lock = new_lock;
}
true
}
pub fn unpark_lock(&self) -> MutexGuard<()> {
self.mutex.lock().unwrap()
}
pub fn unpark(&self, _lock: MutexGuard<()>) {
self.should_park.set(false);
self.condvar.notify_one();
}
}