Skip to main content

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