#[cfg(test)]
mod tests;
use crate::fmt;
use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError};
use crate::sys::locks as sys;
use crate::time::{Duration, Instant};
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[stable(feature = "wait_timeout", since = "1.5.0")]
pub struct WaitTimeoutResult(bool);
impl WaitTimeoutResult {
#[must_use]
#[stable(feature = "wait_timeout", since = "1.5.0")]
pub fn timed_out(&self) -> bool {
self.0
}
}
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Condvar {
inner: sys::Condvar,
}
impl Condvar {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
#[must_use]
#[inline]
pub const fn new() -> Condvar {
Condvar { inner: sys::Condvar::new() }
}
#[stable(feature = "rust1", since = "1.0.0")]
pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a, T>> {
let poisoned = unsafe {
let lock = mutex::guard_lock(&guard);
self.inner.wait(lock);
mutex::guard_poison(&guard).get()
};
if poisoned { Err(PoisonError::new(guard)) } else { Ok(guard) }
}
#[stable(feature = "wait_until", since = "1.42.0")]
pub fn wait_while<'a, T, F>(
&self,
mut guard: MutexGuard<'a, T>,
mut condition: F,
) -> LockResult<MutexGuard<'a, T>>
where
F: FnMut(&mut T) -> bool,
{
while condition(&mut *guard) {
guard = self.wait(guard)?;
}
Ok(guard)
}
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.6.0", note = "replaced by `std::sync::Condvar::wait_timeout`")]
pub fn wait_timeout_ms<'a, T>(
&self,
guard: MutexGuard<'a, T>,
ms: u32,
) -> LockResult<(MutexGuard<'a, T>, bool)> {
let res = self.wait_timeout(guard, Duration::from_millis(ms as u64));
poison::map_result(res, |(a, b)| (a, !b.timed_out()))
}
#[stable(feature = "wait_timeout", since = "1.5.0")]
pub fn wait_timeout<'a, T>(
&self,
guard: MutexGuard<'a, T>,
dur: Duration,
) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
let (poisoned, result) = unsafe {
let lock = mutex::guard_lock(&guard);
let success = self.inner.wait_timeout(lock, dur);
(mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
};
if poisoned { Err(PoisonError::new((guard, result))) } else { Ok((guard, result)) }
}
#[stable(feature = "wait_timeout_until", since = "1.42.0")]
pub fn wait_timeout_while<'a, T, F>(
&self,
mut guard: MutexGuard<'a, T>,
dur: Duration,
mut condition: F,
) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
where
F: FnMut(&mut T) -> bool,
{
let start = Instant::now();
loop {
if !condition(&mut *guard) {
return Ok((guard, WaitTimeoutResult(false)));
}
let timeout = match dur.checked_sub(start.elapsed()) {
Some(timeout) => timeout,
None => return Ok((guard, WaitTimeoutResult(true))),
};
guard = self.wait_timeout(guard, timeout)?.0;
}
}
#[stable(feature = "rust1", since = "1.0.0")]
pub fn notify_one(&self) {
self.inner.notify_one()
}
#[stable(feature = "rust1", since = "1.0.0")]
pub fn notify_all(&self) {
self.inner.notify_all()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Condvar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Condvar").finish_non_exhaustive()
}
}
#[stable(feature = "condvar_default", since = "1.10.0")]
impl Default for Condvar {
fn default() -> Condvar {
Condvar::new()
}
}