use std::time::{
Duration,
Instant,
};
use parking_lot::{
Condvar,
Mutex,
};
use super::parking_lot_monitor_guard::ParkingLotMonitorGuard;
use super::{
ConditionWaiter,
NotificationWaiter,
Notifier,
TimeoutConditionWaiter,
TimeoutNotificationWaiter,
wait_timeout_result::WaitTimeoutResult,
wait_timeout_status::WaitTimeoutStatus,
};
pub struct ParkingLotMonitor<T> {
state: Mutex<T>,
pub(super) changed: Condvar,
}
impl<T> ParkingLotMonitor<T> {
#[inline]
pub fn new(state: T) -> Self {
Self {
state: Mutex::new(state),
changed: Condvar::new(),
}
}
#[inline]
pub fn lock(&self) -> ParkingLotMonitorGuard<'_, T> {
ParkingLotMonitorGuard::new(self, self.state.lock())
}
#[inline]
pub fn read<R, F>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
let guard = self.lock();
f(&*guard)
}
#[inline]
pub fn write<R, F>(&self, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
let mut guard = self.lock();
f(&mut *guard)
}
#[inline]
pub fn write_notify_one<R, F>(&self, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
let result = self.write(f);
self.notify_one();
result
}
#[inline]
pub fn write_notify_all<R, F>(&self, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
let result = self.write(f);
self.notify_all();
result
}
#[inline]
pub fn wait(&self) {
let guard = self.lock();
let _guard = guard.wait();
}
#[inline]
pub fn wait_for(&self, timeout: Duration) -> WaitTimeoutStatus {
let guard = self.lock();
let (_guard, status) = guard.wait_timeout(timeout);
status
}
#[inline]
pub fn wait_while<R, P, F>(&self, mut waiting: P, f: F) -> R
where
P: FnMut(&T) -> bool,
F: FnOnce(&mut T) -> R,
{
let mut guard = self.lock();
while waiting(&*guard) {
guard = guard.wait();
}
f(&mut *guard)
}
#[inline]
pub fn wait_until<R, P, F>(&self, mut ready: P, f: F) -> R
where
P: FnMut(&T) -> bool,
F: FnOnce(&mut T) -> R,
{
self.wait_while(|state| !ready(state), f)
}
#[inline]
pub fn wait_while_for<R, P, F>(
&self,
timeout: Duration,
mut waiting: P,
f: F,
) -> WaitTimeoutResult<R>
where
P: FnMut(&T) -> bool,
F: FnOnce(&mut T) -> R,
{
let mut guard = self.lock();
let start = Instant::now();
loop {
if !waiting(&*guard) {
return WaitTimeoutResult::Ready(f(&mut *guard));
}
let elapsed = start.elapsed();
let remaining = timeout.checked_sub(elapsed).unwrap_or_default();
if remaining.is_zero() {
return WaitTimeoutResult::TimedOut;
}
let (next_guard, _status) = guard.wait_timeout(remaining);
guard = next_guard;
}
}
#[inline]
pub fn wait_until_for<R, P, F>(
&self,
timeout: Duration,
mut ready: P,
f: F,
) -> WaitTimeoutResult<R>
where
P: FnMut(&T) -> bool,
F: FnOnce(&mut T) -> R,
{
self.wait_while_for(timeout, |state| !ready(state), f)
}
#[inline]
pub fn notify_one(&self) {
self.changed.notify_one();
}
#[inline]
pub fn notify_all(&self) {
self.changed.notify_all();
}
}
impl<T> Notifier for ParkingLotMonitor<T> {
#[inline]
fn notify_one(&self) {
Self::notify_one(self);
}
#[inline]
fn notify_all(&self) {
Self::notify_all(self);
}
}
impl<T> NotificationWaiter for ParkingLotMonitor<T> {
#[inline]
fn wait(&self) {
Self::wait(self);
}
}
impl<T> TimeoutNotificationWaiter for ParkingLotMonitor<T> {
#[inline]
fn wait_for(&self, timeout: Duration) -> WaitTimeoutStatus {
Self::wait_for(self, timeout)
}
}
impl<T> ConditionWaiter for ParkingLotMonitor<T> {
type State = T;
#[inline]
fn wait_until<R, P, F>(&self, predicate: P, action: F) -> R
where
P: FnMut(&Self::State) -> bool,
F: FnOnce(&mut Self::State) -> R,
{
Self::wait_until(self, predicate, action)
}
#[inline]
fn wait_while<R, P, F>(&self, predicate: P, action: F) -> R
where
P: FnMut(&Self::State) -> bool,
F: FnOnce(&mut Self::State) -> R,
{
Self::wait_while(self, predicate, action)
}
}
impl<T> TimeoutConditionWaiter for ParkingLotMonitor<T> {
#[inline]
fn wait_until_for<R, P, F>(
&self,
timeout: Duration,
predicate: P,
action: F,
) -> WaitTimeoutResult<R>
where
P: FnMut(&Self::State) -> bool,
F: FnOnce(&mut Self::State) -> R,
{
Self::wait_until_for(self, timeout, predicate, action)
}
#[inline]
fn wait_while_for<R, P, F>(
&self,
timeout: Duration,
predicate: P,
action: F,
) -> WaitTimeoutResult<R>
where
P: FnMut(&Self::State) -> bool,
F: FnOnce(&mut Self::State) -> R,
{
Self::wait_while_for(self, timeout, predicate, action)
}
}
impl<T> From<T> for ParkingLotMonitor<T> {
#[inline]
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: Default> Default for ParkingLotMonitor<T> {
#[inline]
fn default() -> Self {
Self::new(T::default())
}
}