Skip to main content

qubit_lock/monitor/
arc_parking_lot_monitor.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # Arc ParkingLotMonitor
11//!
12//! Provides an Arc-wrapped synchronous monitor for condition-based state
13//! coordination across threads.
14//!
15
16use std::{
17    ops::Deref,
18    sync::Arc,
19    time::Duration,
20};
21
22use super::{
23    ConditionWaiter,
24    NotificationWaiter,
25    Notifier,
26    ParkingLotMonitor,
27    ParkingLotMonitorGuard,
28    TimeoutConditionWaiter,
29    TimeoutNotificationWaiter,
30    WaitTimeoutResult,
31    WaitTimeoutStatus,
32};
33
34/// Arc-wrapped monitor for shared condition-based state coordination.
35///
36/// `ArcParkingLotMonitor` stores a [`ParkingLotMonitor`] behind an [`Arc`], so callers can clone
37/// the monitor handle directly without writing `Arc::new(ParkingLotMonitor::new(...))`.
38/// It preserves the same guard-based waiting and predicate-based waiting
39/// semantics as [`ParkingLotMonitor`]. It implements [`Deref`] and [`AsRef`] so callers
40/// can pass it to APIs that expect a [`ParkingLotMonitor`] reference.
41///
42/// # Type Parameters
43///
44/// * `T` - The state protected by this monitor.
45///
46/// # Example
47///
48/// ```rust
49/// use std::thread;
50///
51/// use qubit_lock::ArcParkingLotMonitor;
52///
53/// let monitor = ArcParkingLotMonitor::new(false);
54/// let waiter_monitor = monitor.clone();
55///
56/// let waiter = thread::spawn(move || {
57///     waiter_monitor.wait_until(
58///         |ready| *ready,
59///         |ready| {
60///             *ready = false;
61///         },
62///     );
63/// });
64///
65/// monitor.write(|ready| {
66///     *ready = true;
67/// });
68/// monitor.notify_all();
69///
70/// waiter.join().expect("waiter should finish");
71/// assert!(!monitor.read(|ready| *ready));
72/// ```
73///
74pub struct ArcParkingLotMonitor<T> {
75    /// Shared monitor instance.
76    inner: Arc<ParkingLotMonitor<T>>,
77}
78
79impl<T> ArcParkingLotMonitor<T> {
80    /// Creates an Arc-wrapped monitor protecting the supplied state value.
81    ///
82    /// # Arguments
83    ///
84    /// * `state` - Initial state protected by the monitor.
85    ///
86    /// # Returns
87    ///
88    /// A cloneable monitor handle initialized with the supplied state.
89    #[inline]
90    pub fn new(state: T) -> Self {
91        Self {
92            inner: Arc::new(ParkingLotMonitor::new(state)),
93        }
94    }
95
96    /// Acquires the shared monitor and returns a guard.
97    ///
98    /// This delegates to [`ParkingLotMonitor::lock`]. The returned [`ParkingLotMonitorGuard`]
99    /// keeps the monitor mutex locked until it is dropped. It can also wait on
100    /// the monitor's condition variable through [`ParkingLotMonitorGuard::wait`] or
101    /// [`ParkingLotMonitorGuard::wait_timeout`].
102    ///
103    /// # Returns
104    ///
105    /// A guard that provides read and write access to the protected state.
106    ///
107    /// # Example
108    ///
109    /// ```rust
110    /// use qubit_lock::ArcParkingLotMonitor;
111    ///
112    /// let monitor = ArcParkingLotMonitor::new(1);
113    /// {
114    ///     let mut value = monitor.lock();
115    ///     *value += 1;
116    /// }
117    ///
118    /// assert_eq!(monitor.read(|value| *value), 2);
119    /// ```
120    #[inline]
121    pub fn lock(&self) -> ParkingLotMonitorGuard<'_, T> {
122        self.inner.lock()
123    }
124
125    /// Acquires the monitor and reads the protected state.
126    ///
127    /// This delegates to [`ParkingLotMonitor::read`]. The closure runs while the monitor
128    /// mutex is held, so keep it short and avoid long blocking work.
129    ///
130    /// # Arguments
131    ///
132    /// * `f` - Closure that receives an immutable reference to the state.
133    ///
134    /// # Returns
135    ///
136    /// The value returned by `f`.
137    #[inline]
138    pub fn read<R, F>(&self, f: F) -> R
139    where
140        F: FnOnce(&T) -> R,
141    {
142        self.inner.read(f)
143    }
144
145    /// Acquires the monitor and mutates the protected state.
146    ///
147    /// This delegates to [`ParkingLotMonitor::write`]. Callers should explicitly invoke
148    /// [`Self::notify_one`] or [`Self::notify_all`] after changing state that a
149    /// waiting thread may observe.
150    ///
151    /// # Arguments
152    ///
153    /// * `f` - Closure that receives a mutable reference to the state.
154    ///
155    /// # Returns
156    ///
157    /// The value returned by `f`.
158    #[inline]
159    pub fn write<R, F>(&self, f: F) -> R
160    where
161        F: FnOnce(&mut T) -> R,
162    {
163        self.inner.write(f)
164    }
165
166    /// Mutates the protected state and wakes one waiter.
167    ///
168    /// This delegates to [`ParkingLotMonitor::write_notify_one`]. The closure runs while
169    /// the monitor mutex is held; after it returns, the lock is released and one
170    /// waiter is notified. If `f` panics, the panic is propagated and no
171    /// notification is sent.
172    ///
173    /// # Arguments
174    ///
175    /// * `f` - Closure that receives a mutable reference to the state.
176    ///
177    /// # Returns
178    ///
179    /// The value returned by `f`.
180    #[inline]
181    pub fn write_notify_one<R, F>(&self, f: F) -> R
182    where
183        F: FnOnce(&mut T) -> R,
184    {
185        self.inner.write_notify_one(f)
186    }
187
188    /// Mutates the protected state and wakes all waiters.
189    ///
190    /// This delegates to [`ParkingLotMonitor::write_notify_all`]. The closure runs while
191    /// the monitor mutex is held; after it returns, the lock is released and all
192    /// waiters are notified. If `f` panics, the panic is propagated and no
193    /// notification is sent.
194    ///
195    /// # Arguments
196    ///
197    /// * `f` - Closure that receives a mutable reference to the state.
198    ///
199    /// # Returns
200    ///
201    /// The value returned by `f`.
202    #[inline]
203    pub fn write_notify_all<R, F>(&self, f: F) -> R
204    where
205        F: FnOnce(&mut T) -> R,
206    {
207        self.inner.write_notify_all(f)
208    }
209
210    /// Waits for a notification without checking state.
211    ///
212    /// This delegates to [`ParkingLotMonitor::wait`].
213    #[inline]
214    pub fn wait(&self) {
215        self.inner.wait();
216    }
217
218    /// Waits for a notification or timeout without checking state.
219    ///
220    /// This delegates to [`ParkingLotMonitor::wait_for`]. Most
221    /// coordination code should prefer [`Self::wait_while`],
222    /// [`Self::wait_until`], or an explicit [`ParkingLotMonitorGuard`] loop.
223    ///
224    /// [`WaitTimeoutStatus::Woken`] means the condition variable was notified,
225    /// but it does not prove that the protected state changed in a useful way.
226    ///
227    /// # Arguments
228    ///
229    /// * `timeout` - Maximum duration to wait for a notification.
230    ///
231    /// # Returns
232    ///
233    /// [`WaitTimeoutStatus::Woken`] if the wait returned before the timeout,
234    /// or [`WaitTimeoutStatus::TimedOut`] if the timeout elapsed.
235    ///
236    /// # Example
237    ///
238    /// ```rust
239    /// use std::time::Duration;
240    ///
241    /// use qubit_lock::{ArcParkingLotMonitor, WaitTimeoutStatus};
242    ///
243    /// let monitor = ArcParkingLotMonitor::new(false);
244    /// let status = monitor.wait_for(Duration::from_millis(1));
245    ///
246    /// assert_eq!(status, WaitTimeoutStatus::TimedOut);
247    /// ```
248    #[inline]
249    pub fn wait_for(&self, timeout: Duration) -> WaitTimeoutStatus {
250        self.inner.wait_for(timeout)
251    }
252
253    /// Waits while a predicate remains true, then mutates the protected state.
254    ///
255    /// This delegates to [`ParkingLotMonitor::wait_while`]. The predicate is evaluated
256    /// while holding the monitor mutex, and the closure runs while the mutex is
257    /// still held after the predicate stops blocking.
258    ///
259    /// This method may block indefinitely if no thread changes the state so
260    /// that `waiting` becomes false and sends a notification.
261    ///
262    /// # Arguments
263    ///
264    /// * `waiting` - Predicate that returns `true` while the caller should
265    ///   keep waiting.
266    /// * `f` - Closure that receives mutable access after waiting is no longer
267    ///   required.
268    ///
269    /// # Returns
270    ///
271    /// The value returned by `f`.
272    ///
273    /// # Example
274    ///
275    /// ```rust
276    /// use std::thread;
277    ///
278    /// use qubit_lock::ArcParkingLotMonitor;
279    ///
280    /// let monitor = ArcParkingLotMonitor::new(Vec::<i32>::new());
281    /// let worker_monitor = monitor.clone();
282    ///
283    /// let worker = thread::spawn(move || {
284    ///     worker_monitor.wait_while(
285    ///         |items| items.is_empty(),
286    ///         |items| items.pop().expect("item should be ready"),
287    ///     )
288    /// });
289    ///
290    /// monitor.write(|items| items.push(7));
291    /// monitor.notify_one();
292    ///
293    /// assert_eq!(worker.join().expect("worker should finish"), 7);
294    /// ```
295    #[inline]
296    pub fn wait_while<R, P, F>(&self, waiting: P, f: F) -> R
297    where
298        P: FnMut(&T) -> bool,
299        F: FnOnce(&mut T) -> R,
300    {
301        self.inner.wait_while(waiting, f)
302    }
303
304    /// Waits until the protected state satisfies a predicate, then mutates it.
305    ///
306    /// This delegates to [`ParkingLotMonitor::wait_until`]. It may block indefinitely if
307    /// no thread changes the state to satisfy the predicate and sends a
308    /// notification.
309    ///
310    /// # Arguments
311    ///
312    /// * `ready` - Predicate that returns `true` when the state is ready.
313    /// * `f` - Closure that receives mutable access to the ready state.
314    ///
315    /// # Returns
316    ///
317    /// The value returned by `f`.
318    #[inline]
319    pub fn wait_until<R, P, F>(&self, ready: P, f: F) -> R
320    where
321        P: FnMut(&T) -> bool,
322        F: FnOnce(&mut T) -> R,
323    {
324        self.inner.wait_until(ready, f)
325    }
326
327    /// Waits while a predicate remains true, with an overall time limit.
328    ///
329    /// This delegates to [`ParkingLotMonitor::wait_while_for`]. If `waiting` becomes
330    /// false before `timeout` expires, `f` runs while the monitor lock is still
331    /// held. If the timeout expires first, the closure is not called.
332    ///
333    /// # Arguments
334    ///
335    /// * `timeout` - Maximum total duration to wait.
336    /// * `waiting` - Predicate that returns `true` while the caller should
337    ///   continue waiting.
338    /// * `f` - Closure that receives mutable access when waiting is no longer
339    ///   required.
340    ///
341    /// # Returns
342    ///
343    /// [`WaitTimeoutResult::Ready`] with the value returned by `f` when the
344    /// predicate stops blocking before the timeout. Returns
345    /// [`WaitTimeoutResult::TimedOut`] when the timeout expires first.
346    ///
347    /// # Example
348    ///
349    /// ```rust
350    /// use std::time::Duration;
351    ///
352    /// use qubit_lock::{ArcParkingLotMonitor, WaitTimeoutResult};
353    ///
354    /// let monitor = ArcParkingLotMonitor::new(Vec::<i32>::new());
355    /// let result = monitor.wait_while_for(
356    ///     Duration::from_millis(1),
357    ///     |items| items.is_empty(),
358    ///     |items| items.pop(),
359    /// );
360    ///
361    /// assert_eq!(result, WaitTimeoutResult::TimedOut);
362    /// ```
363    #[inline]
364    pub fn wait_while_for<R, P, F>(
365        &self,
366        timeout: Duration,
367        waiting: P,
368        f: F,
369    ) -> WaitTimeoutResult<R>
370    where
371        P: FnMut(&T) -> bool,
372        F: FnOnce(&mut T) -> R,
373    {
374        self.inner.wait_while_for(timeout, waiting, f)
375    }
376
377    /// Waits until a predicate becomes true, with an overall time limit.
378    ///
379    /// This delegates to [`ParkingLotMonitor::wait_until_for`]. If `ready` becomes
380    /// true before `timeout` expires, `f` runs while the monitor lock is still
381    /// held. If the timeout expires first, the closure is not called.
382    ///
383    /// # Arguments
384    ///
385    /// * `timeout` - Maximum total duration to wait.
386    /// * `ready` - Predicate that returns `true` when the caller may continue.
387    /// * `f` - Closure that receives mutable access to the ready state.
388    ///
389    /// # Returns
390    ///
391    /// [`WaitTimeoutResult::Ready`] with the value returned by `f` when the
392    /// predicate becomes true before the timeout. Returns
393    /// [`WaitTimeoutResult::TimedOut`] when the timeout expires first.
394    ///
395    /// # Example
396    ///
397    /// ```rust
398    /// use std::{
399    ///     thread,
400    ///     time::Duration,
401    /// };
402    ///
403    /// use qubit_lock::{ArcParkingLotMonitor, WaitTimeoutResult};
404    ///
405    /// let monitor = ArcParkingLotMonitor::new(false);
406    /// let worker_monitor = monitor.clone();
407    ///
408    /// let worker = thread::spawn(move || {
409    ///     worker_monitor.wait_until_for(
410    ///         Duration::from_secs(1),
411    ///         |ready| *ready,
412    ///         |ready| {
413    ///             *ready = false;
414    ///             5
415    ///         },
416    ///     )
417    /// });
418    ///
419    /// monitor.write(|ready| *ready = true);
420    /// monitor.notify_one();
421    ///
422    /// assert_eq!(
423    ///     worker.join().expect("worker should finish"),
424    ///     WaitTimeoutResult::Ready(5),
425    /// );
426    /// ```
427    #[inline]
428    pub fn wait_until_for<R, P, F>(&self, timeout: Duration, ready: P, f: F) -> WaitTimeoutResult<R>
429    where
430        P: FnMut(&T) -> bool,
431        F: FnOnce(&mut T) -> R,
432    {
433        self.inner.wait_until_for(timeout, ready, f)
434    }
435
436    /// Wakes one thread waiting on this monitor's condition variable.
437    ///
438    /// Notifications do not carry state by themselves. A waiting thread only
439    /// proceeds safely after rechecking the protected state. Call this after
440    /// changing state that may make one waiter able to continue.
441    #[inline]
442    pub fn notify_one(&self) {
443        self.inner.notify_one();
444    }
445
446    /// Wakes all threads waiting on this monitor's condition variable.
447    ///
448    /// Notifications do not carry state by themselves. Every awakened thread
449    /// must recheck the protected state before continuing. Call this after a
450    /// state change that may allow multiple waiters to make progress.
451    #[inline]
452    pub fn notify_all(&self) {
453        self.inner.notify_all();
454    }
455}
456
457impl<T> AsRef<ParkingLotMonitor<T>> for ArcParkingLotMonitor<T> {
458    /// Returns a reference to the underlying monitor.
459    ///
460    /// This is useful when callers need an explicit [`ParkingLotMonitor`] reference while
461    /// keeping the cloneable [`ArcParkingLotMonitor`] handle.
462    #[inline]
463    fn as_ref(&self) -> &ParkingLotMonitor<T> {
464        self.inner.as_ref()
465    }
466}
467
468impl<T> Notifier for ArcParkingLotMonitor<T> {
469    /// Wakes one thread waiting on this monitor.
470    #[inline]
471    fn notify_one(&self) {
472        Self::notify_one(self);
473    }
474
475    /// Wakes all threads waiting on this monitor.
476    #[inline]
477    fn notify_all(&self) {
478        Self::notify_all(self);
479    }
480}
481
482impl<T> NotificationWaiter for ArcParkingLotMonitor<T> {
483    /// Blocks until a notification wakes this waiter.
484    #[inline]
485    fn wait(&self) {
486        Self::wait(self);
487    }
488}
489
490impl<T> TimeoutNotificationWaiter for ArcParkingLotMonitor<T> {
491    /// Blocks until a notification wakes this waiter or the timeout expires.
492    #[inline]
493    fn wait_for(&self, timeout: Duration) -> WaitTimeoutStatus {
494        Self::wait_for(self, timeout)
495    }
496}
497
498impl<T> ConditionWaiter for ArcParkingLotMonitor<T> {
499    type State = T;
500
501    /// Blocks until the predicate becomes true, then runs the action.
502    #[inline]
503    fn wait_until<R, P, F>(&self, predicate: P, action: F) -> R
504    where
505        P: FnMut(&Self::State) -> bool,
506        F: FnOnce(&mut Self::State) -> R,
507    {
508        Self::wait_until(self, predicate, action)
509    }
510
511    /// Blocks while the predicate remains true, then runs the action.
512    #[inline]
513    fn wait_while<R, P, F>(&self, predicate: P, action: F) -> R
514    where
515        P: FnMut(&Self::State) -> bool,
516        F: FnOnce(&mut Self::State) -> R,
517    {
518        Self::wait_while(self, predicate, action)
519    }
520}
521
522impl<T> TimeoutConditionWaiter for ArcParkingLotMonitor<T> {
523    /// Blocks until the predicate becomes true or the timeout expires.
524    #[inline]
525    fn wait_until_for<R, P, F>(
526        &self,
527        timeout: Duration,
528        predicate: P,
529        action: F,
530    ) -> WaitTimeoutResult<R>
531    where
532        P: FnMut(&Self::State) -> bool,
533        F: FnOnce(&mut Self::State) -> R,
534    {
535        Self::wait_until_for(self, timeout, predicate, action)
536    }
537
538    /// Blocks while the predicate remains true or until the timeout expires.
539    #[inline]
540    fn wait_while_for<R, P, F>(
541        &self,
542        timeout: Duration,
543        predicate: P,
544        action: F,
545    ) -> WaitTimeoutResult<R>
546    where
547        P: FnMut(&Self::State) -> bool,
548        F: FnOnce(&mut Self::State) -> R,
549    {
550        Self::wait_while_for(self, timeout, predicate, action)
551    }
552}
553
554impl<T> Deref for ArcParkingLotMonitor<T> {
555    type Target = ParkingLotMonitor<T>;
556
557    /// Dereferences this wrapper to the underlying monitor.
558    ///
559    /// Method-call dereferencing lets callers use native [`ParkingLotMonitor`] APIs
560    /// directly, while this wrapper still provides cloneable ownership.
561    #[inline]
562    fn deref(&self) -> &Self::Target {
563        self.inner.as_ref()
564    }
565}
566
567impl<T> From<T> for ArcParkingLotMonitor<T> {
568    /// Creates an Arc-wrapped monitor from an initial state value.
569    ///
570    /// # Arguments
571    ///
572    /// * `value` - Initial state protected by the monitor.
573    ///
574    /// # Returns
575    ///
576    /// A cloneable monitor handle protecting `value`.
577    #[inline]
578    fn from(value: T) -> Self {
579        Self::new(value)
580    }
581}
582
583impl<T: Default> Default for ArcParkingLotMonitor<T> {
584    /// Creates an Arc-wrapped monitor containing `T::default()`.
585    ///
586    /// # Returns
587    ///
588    /// A cloneable monitor handle protecting the default value for `T`.
589    #[inline]
590    fn default() -> Self {
591        Self::new(T::default())
592    }
593}
594
595impl<T> Clone for ArcParkingLotMonitor<T> {
596    /// Clones this monitor handle.
597    ///
598    /// The cloned handle shares the same protected state and condition
599    /// variable with the original.
600    ///
601    /// # Returns
602    ///
603    /// A new handle sharing the same monitor state.
604    #[inline]
605    fn clone(&self) -> Self {
606        Self {
607            inner: self.inner.clone(),
608        }
609    }
610}