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}