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}