blob: bceba2f859f389c20e039f1228bd27fabea125f8 [file] [log] [blame] [edit]
use crate::traits::Sealed;
use core::{mem::ManuallyDrop, ptr};
#[cfg(feature = "std")]
use std::{
sync::{Condvar, LockResult, MutexGuard, WaitTimeoutResult},
time::{Duration, Instant},
};
#[cfg(feature = "std")]
#[inline(always)]
fn new_wait_timeout_result(value: bool) -> WaitTimeoutResult {
// Safety: WaitTimeoutResult is a thin wrapper around a boolean. As the
// structure is not public, we must transmute the provided boolean to
// construct the desired value. If the internal size changes in the future,
// this will stop compiling.
unsafe { core::mem::transmute(value) }
}
#[cfg(feature = "std")]
pub trait Condvar_v1_42: Sealed<Condvar> {
fn wait_while<'a, T, F>(
&self,
guard: MutexGuard<'a, T>,
condition: F,
) -> LockResult<MutexGuard<'a, T>>
where
F: FnMut(&mut T) -> bool;
fn wait_timeout_while<'a, T, F>(
&self,
guard: MutexGuard<'a, T>,
dur: Duration,
condition: F,
) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
where
F: FnMut(&mut T) -> bool;
}
#[cfg(feature = "std")]
impl Condvar_v1_42 for Condvar {
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)
}
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, new_wait_timeout_result(false)));
}
let timeout = match dur.checked_sub(start.elapsed()) {
Some(timeout) => timeout,
None => return Ok((guard, new_wait_timeout_result(true))),
};
guard = self.wait_timeout(guard, timeout)?.0;
}
}
}
pub trait ManuallyDrop_v1_42<T>: Sealed<ManuallyDrop<T>> {
unsafe fn take(slot: &mut ManuallyDrop<T>) -> T;
}
impl<T> ManuallyDrop_v1_42<T> for ManuallyDrop<T> {
#[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
#[inline]
unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
ptr::read(slot as *mut _ as *const _)
}
}
#[macro_export]
macro_rules! matches {
($expression:expr, $( $pattern:pat )|+) => {
match $expression {
$( $pattern )|+ => true,
_ => false,
}
};
($expression:expr, $( $pattern:pat )|+ if $guard:expr) => {
match $expression {
$( $pattern )|+ if $guard => true,
_ => false
}
}
}