use core::mem;
use std::sync::{Condvar, Mutex, MutexGuard};
use std::time::Instant;
pub struct ThreadParker {
should_park: Mutex<bool>,
condvar: Condvar,
}
impl super::ThreadParkerT for ThreadParker {
type UnparkHandle = UnparkHandle;
const IS_CHEAP_TO_CONSTRUCT: bool = true;
#[inline]
fn new() -> ThreadParker {
ThreadParker {
should_park: Mutex::new(false),
condvar: Condvar::new(),
}
}
#[inline]
unsafe fn prepare_park(&self) {
*self.should_park.lock().unwrap() = true;
}
#[inline]
unsafe fn timed_out(&self) -> bool {
*self.should_park.lock().unwrap()
}
#[inline]
unsafe fn park(&self) {
let mut should_park = self.should_park.lock().unwrap();
while *should_park {
should_park = self.condvar.wait(should_park).unwrap();
}
}
#[inline]
unsafe fn park_until(&self, timeout: Instant) -> bool {
let mut should_park = self.should_park.lock().unwrap();
while *should_park {
let now = Instant::now();
if now >= timeout {
return false;
}
let (guard, _) = self
.condvar
.wait_timeout(should_park, timeout - now)
.unwrap();
should_park = guard;
}
true
}
#[inline]
unsafe fn unpark_lock(&self) -> UnparkHandle {
let guard = self.should_park.lock().unwrap();
UnparkHandle {
guard: mem::transmute::<MutexGuard<'_, bool>, MutexGuard<'static, bool>>(guard),
condvar: &self.condvar,
}
}
}
pub struct UnparkHandle {
guard: MutexGuard<'static, bool>,
condvar: *const Condvar,
}
impl super::UnparkHandleT for UnparkHandle {
#[inline]
unsafe fn unpark(mut self) {
*self.guard = false;
(*self.condvar).notify_one();
drop(self.guard);
}
}
#[inline]
pub fn thread_yield() {
std::thread::yield_now();
}