qubit_lock/monitor/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//! # ParkingLotMonitor
11//!
12//! Provides a synchronous monitor built from a mutex and a condition variable.
13//! A monitor protects one shared state value and binds that state to the
14//! condition variable used to wait for changes. This is the same low-level
15//! mechanism as using [`parking_lot::Mutex`] and [`parking_lot::Condvar`] directly,
16//! but packaged so callers do not have to keep a mutex and its matching
17//! condition variable as separate fields.
18//!
19//! The high-level APIs ([`ParkingLotMonitor::read`], [`ParkingLotMonitor::write`],
20//! [`ParkingLotMonitor::wait_while`], and [`ParkingLotMonitor::wait_until`]) are intended for
21//! short critical sections and simple guarded-suspension flows. The lower-level
22//! [`ParkingLotMonitor::lock`] API returns a [`ParkingLotMonitorGuard`], which supports
23//! [`ParkingLotMonitorGuard::wait`] and [`ParkingLotMonitorGuard::wait_timeout`] for more complex
24//! state machines such as thread pools.
25//!
26
27use std::time::{
28 Duration,
29 Instant,
30};
31
32use parking_lot::{
33 Condvar,
34 Mutex,
35};
36
37use super::parking_lot_monitor_guard::ParkingLotMonitorGuard;
38use super::{
39 ConditionWaiter,
40 NotificationWaiter,
41 Notifier,
42 TimeoutConditionWaiter,
43 TimeoutNotificationWaiter,
44 wait_timeout_result::WaitTimeoutResult,
45 wait_timeout_status::WaitTimeoutStatus,
46};
47
48/// Shared state protected by a mutex and a condition variable.
49///
50/// `ParkingLotMonitor` is useful when callers need more than a short critical section.
51/// It models the classic monitor object pattern: one mutex protects the state,
52/// and one condition variable lets threads wait until that state changes. This
53/// is the same relationship used by `parking_lot::Mutex` and
54/// `parking_lot::Condvar`, but represented as one object so the condition
55/// variable is not accidentally used with unrelated state.
56///
57/// `ParkingLotMonitor` deliberately has two levels of API:
58///
59/// * `read` and `write` acquire the mutex, run a closure, and release it.
60/// * `wait_while`, `wait_until`, and their timeout variants implement common
61/// predicate-based waits.
62/// * `lock` returns a [`ParkingLotMonitorGuard`] for callers that need to write their own
63/// loop around [`ParkingLotMonitorGuard::wait`] or [`ParkingLotMonitorGuard::wait_timeout`].
64///
65/// The underlying `parking_lot` mutex is not poisoned when a thread panics
66/// while holding the lock. This keeps monitor coordination state observable
67/// after panic unwinding.
68///
69/// # Difference from raw `Mutex` and `Condvar`
70///
71/// With raw parking_lot primitives, callers usually store two fields and
72/// manually keep them paired:
73///
74/// ```rust
75/// # use parking_lot::{Condvar, Mutex};
76/// # struct State;
77/// struct Shared {
78/// state: Mutex<State>,
79/// changed: Condvar,
80/// }
81/// ```
82///
83/// `ParkingLotMonitor<State>` stores the same pair internally. A [`ParkingLotMonitorGuard`] is a
84/// wrapper around the parking_lot `MutexGuard`; it keeps the protected
85/// state locked and knows which monitor it belongs to, so its wait methods use
86/// the matching condition variable.
87///
88/// # Type Parameters
89///
90/// * `T` - The state protected by this monitor.
91///
92/// # Example
93///
94/// ```rust
95/// use std::thread;
96///
97/// use qubit_lock::ArcParkingLotMonitor;
98///
99/// let monitor = ArcParkingLotMonitor::new(false);
100/// let waiter_monitor = monitor.clone();
101///
102/// let waiter = thread::spawn(move || {
103/// waiter_monitor.wait_until(
104/// |ready| *ready,
105/// |ready| {
106/// *ready = false;
107/// },
108/// );
109/// });
110///
111/// monitor.write(|ready| {
112/// *ready = true;
113/// });
114/// monitor.notify_all();
115///
116/// waiter.join().expect("waiter should finish");
117/// assert!(!monitor.read(|ready| *ready));
118/// ```
119///
120pub struct ParkingLotMonitor<T> {
121 /// Mutex protecting the monitor state.
122 state: Mutex<T>,
123 /// Condition variable used to wake predicate waiters after state changes.
124 pub(super) changed: Condvar,
125}
126
127impl<T> ParkingLotMonitor<T> {
128 /// Creates a monitor protecting the supplied state value.
129 ///
130 /// # Arguments
131 ///
132 /// * `state` - Initial state protected by the monitor.
133 ///
134 /// # Returns
135 ///
136 /// A monitor initialized with the supplied state.
137 ///
138 /// # Example
139 ///
140 /// ```rust
141 /// use qubit_lock::ParkingLotMonitor;
142 ///
143 /// let monitor = ParkingLotMonitor::new(0_u32);
144 /// assert_eq!(monitor.read(|n| *n), 0);
145 /// ```
146 #[inline]
147 pub fn new(state: T) -> Self {
148 Self {
149 state: Mutex::new(state),
150 changed: Condvar::new(),
151 }
152 }
153
154 /// Acquires the monitor and returns a guard for explicit state-machine code.
155 ///
156 /// The returned [`ParkingLotMonitorGuard`] keeps the monitor mutex locked until the
157 /// guard is dropped. It can also be passed through
158 /// [`ParkingLotMonitorGuard::wait`] or [`ParkingLotMonitorGuard::wait_timeout`] to temporarily
159 /// release the lock while waiting on this monitor's condition variable.
160 ///
161 /// # Returns
162 ///
163 /// A guard that provides read and write access to the protected state.
164 ///
165 /// # Example
166 ///
167 /// ```rust
168 /// use qubit_lock::ParkingLotMonitor;
169 ///
170 /// let monitor = ParkingLotMonitor::new(1);
171 /// {
172 /// let mut value = monitor.lock();
173 /// *value += 1;
174 /// }
175 ///
176 /// assert_eq!(monitor.read(|value| *value), 2);
177 /// ```
178 #[inline]
179 pub fn lock(&self) -> ParkingLotMonitorGuard<'_, T> {
180 ParkingLotMonitorGuard::new(self, self.state.lock())
181 }
182
183 /// Acquires the monitor and reads the protected state.
184 ///
185 /// The closure runs while the mutex is held. Keep the closure short and do
186 /// not call code that may block for a long time.
187 ///
188 /// # Arguments
189 ///
190 /// * `f` - Closure that receives an immutable reference to the state.
191 ///
192 /// # Returns
193 ///
194 /// The value returned by the closure.
195 ///
196 /// # Example
197 ///
198 /// ```rust
199 /// use qubit_lock::ParkingLotMonitor;
200 ///
201 /// let monitor = ParkingLotMonitor::new(10_i32);
202 /// let n = monitor.read(|x| *x);
203 /// assert_eq!(n, 10);
204 /// ```
205 #[inline]
206 pub fn read<R, F>(&self, f: F) -> R
207 where
208 F: FnOnce(&T) -> R,
209 {
210 let guard = self.lock();
211 f(&*guard)
212 }
213
214 /// Acquires the monitor and mutates the protected state.
215 ///
216 /// The closure runs while the mutex is held. This method only changes the
217 /// state; callers should explicitly call [`Self::notify_one`] or
218 /// [`Self::notify_all`] after changing a condition that waiters may be
219 /// observing.
220 ///
221 /// # Arguments
222 ///
223 /// * `f` - Closure that receives a mutable reference to the state.
224 ///
225 /// # Returns
226 ///
227 /// The value returned by the closure.
228 ///
229 /// # Example
230 ///
231 /// ```rust
232 /// use qubit_lock::ParkingLotMonitor;
233 ///
234 /// let monitor = ParkingLotMonitor::new(String::new());
235 /// let len = monitor.write(|s| {
236 /// s.push_str("hi");
237 /// s.len()
238 /// });
239 /// assert_eq!(len, 2);
240 /// ```
241 #[inline]
242 pub fn write<R, F>(&self, f: F) -> R
243 where
244 F: FnOnce(&mut T) -> R,
245 {
246 let mut guard = self.lock();
247 f(&mut *guard)
248 }
249
250 /// Acquires the monitor, mutates the protected state, and wakes one waiter.
251 ///
252 /// The closure runs while the mutex is held. After the closure returns, the
253 /// mutex guard is dropped and one thread waiting on this monitor's condition
254 /// variable is notified. This is a convenience method for the common
255 /// "update state, then notify one waiter" pattern.
256 ///
257 /// If `f` panics, the panic is propagated and no notification is sent.
258 ///
259 /// # Arguments
260 ///
261 /// * `f` - Closure that receives a mutable reference to the state.
262 ///
263 /// # Returns
264 ///
265 /// The value returned by the closure.
266 ///
267 /// # Example
268 ///
269 /// ```rust
270 /// use qubit_lock::ParkingLotMonitor;
271 ///
272 /// let monitor = ParkingLotMonitor::new(Vec::<i32>::new());
273 /// let len = monitor.write_notify_one(|items| {
274 /// items.push(7);
275 /// items.len()
276 /// });
277 ///
278 /// assert_eq!(len, 1);
279 /// ```
280 #[inline]
281 pub fn write_notify_one<R, F>(&self, f: F) -> R
282 where
283 F: FnOnce(&mut T) -> R,
284 {
285 let result = self.write(f);
286 self.notify_one();
287 result
288 }
289
290 /// Acquires the monitor, mutates the protected state, and wakes all waiters.
291 ///
292 /// The closure runs while the mutex is held. After the closure returns, the
293 /// mutex guard is dropped and all threads waiting on this monitor's condition
294 /// variable are notified. This is a convenience method for state changes that
295 /// may allow multiple waiters to make progress.
296 ///
297 /// If `f` panics, the panic is propagated and no notification is sent.
298 ///
299 /// # Arguments
300 ///
301 /// * `f` - Closure that receives a mutable reference to the state.
302 ///
303 /// # Returns
304 ///
305 /// The value returned by the closure.
306 ///
307 /// # Example
308 ///
309 /// ```rust
310 /// use qubit_lock::ParkingLotMonitor;
311 ///
312 /// let monitor = ParkingLotMonitor::new(false);
313 /// let ready = monitor.write_notify_all(|ready| {
314 /// *ready = true;
315 /// *ready
316 /// });
317 ///
318 /// assert!(ready);
319 /// ```
320 #[inline]
321 pub fn write_notify_all<R, F>(&self, f: F) -> R
322 where
323 F: FnOnce(&mut T) -> R,
324 {
325 let result = self.write(f);
326 self.notify_all();
327 result
328 }
329
330 /// Waits for a notification without checking state.
331 ///
332 /// This method locks the monitor, waits once on the condition variable,
333 /// and returns after the wait is woken. Most coordination code should
334 /// prefer [`Self::wait_while`], [`Self::wait_until`], or an explicit
335 /// [`ParkingLotMonitorGuard`] loop that rechecks protected state.
336 ///
337 /// This method may block indefinitely if no notification is sent.
338 #[inline]
339 pub fn wait(&self) {
340 let guard = self.lock();
341 let _guard = guard.wait();
342 }
343
344 /// Waits for a notification or timeout without checking state.
345 ///
346 /// This convenience method locks the monitor, waits once on the condition
347 /// variable, and returns why the timed wait completed. It is useful only
348 /// when the caller genuinely needs a notification wait without inspecting
349 /// state before or after the wait. Most coordination code should prefer
350 /// [`Self::wait_while`], [`Self::wait_until`], or the explicit
351 /// [`ParkingLotMonitorGuard::wait_timeout`] loop.
352 ///
353 /// [`WaitTimeoutStatus::Woken`] means the condition variable was notified,
354 /// but it does not prove that the protected state changed in a useful way.
355 ///
356 /// # Arguments
357 ///
358 /// * `timeout` - Maximum duration to wait for a notification.
359 ///
360 /// # Returns
361 ///
362 /// [`WaitTimeoutStatus::Woken`] if the wait returned before the timeout,
363 /// or [`WaitTimeoutStatus::TimedOut`] if the timeout elapsed.
364 ///
365 /// # Example
366 ///
367 /// ```rust
368 /// use std::time::Duration;
369 ///
370 /// use qubit_lock::{ParkingLotMonitor, WaitTimeoutStatus};
371 ///
372 /// let monitor = ParkingLotMonitor::new(false);
373 /// let status = monitor.wait_for(Duration::from_millis(1));
374 ///
375 /// assert_eq!(status, WaitTimeoutStatus::TimedOut);
376 /// ```
377 #[inline]
378 pub fn wait_for(&self, timeout: Duration) -> WaitTimeoutStatus {
379 let guard = self.lock();
380 let (_guard, status) = guard.wait_timeout(timeout);
381 status
382 }
383
384 /// Waits while a predicate remains true, then mutates the protected state.
385 ///
386 /// This is the monitor equivalent of the common `while condition { wait }`
387 /// guarded-suspension pattern. The predicate is evaluated while holding the
388 /// mutex. If it returns `true`, the current thread waits on the condition
389 /// variable and atomically releases the mutex. After a notification, the
390 /// mutex is reacquired and the predicate is evaluated again. When the
391 /// predicate returns `false`, `f` runs while the mutex is still held.
392 ///
393 /// This method may block indefinitely if no thread changes the state so
394 /// that `waiting` becomes false and sends a notification.
395 ///
396 /// # Arguments
397 ///
398 /// * `waiting` - Predicate that returns `true` while the caller should
399 /// keep waiting.
400 /// * `f` - Closure that receives mutable access after waiting is no longer
401 /// required.
402 ///
403 /// # Returns
404 ///
405 /// The value returned by `f`.
406 ///
407 /// # Example
408 ///
409 /// ```rust
410 /// use std::{
411 /// sync::Arc,
412 /// thread,
413 /// };
414 ///
415 /// use qubit_lock::ParkingLotMonitor;
416 ///
417 /// let monitor = Arc::new(ParkingLotMonitor::new(Vec::<i32>::new()));
418 /// let worker_monitor = Arc::clone(&monitor);
419 ///
420 /// let worker = thread::spawn(move || {
421 /// worker_monitor.wait_while(
422 /// |items| items.is_empty(),
423 /// |items| items.pop().expect("item should be ready"),
424 /// )
425 /// });
426 ///
427 /// monitor.write(|items| items.push(7));
428 /// monitor.notify_one();
429 ///
430 /// assert_eq!(worker.join().expect("worker should finish"), 7);
431 /// ```
432 #[inline]
433 pub fn wait_while<R, P, F>(&self, mut waiting: P, f: F) -> R
434 where
435 P: FnMut(&T) -> bool,
436 F: FnOnce(&mut T) -> R,
437 {
438 let mut guard = self.lock();
439 while waiting(&*guard) {
440 guard = guard.wait();
441 }
442 f(&mut *guard)
443 }
444
445 /// Waits until the protected state satisfies a predicate, then mutates it.
446 ///
447 /// This is the positive-predicate counterpart of [`Self::wait_while`]. The
448 /// predicate is evaluated while holding the mutex. If it returns `false`,
449 /// the current thread waits on the condition variable and atomically
450 /// releases the mutex. After a notification, the mutex is reacquired and
451 /// the predicate is evaluated again. When the predicate returns `true`, `f`
452 /// runs while the mutex is still held.
453 ///
454 /// This method may block indefinitely if no thread changes the state to
455 /// satisfy the predicate and sends a notification.
456 ///
457 /// # Arguments
458 ///
459 /// * `ready` - Predicate that returns `true` when the state is ready.
460 /// * `f` - Closure that receives mutable access to the ready state.
461 ///
462 /// # Returns
463 ///
464 /// The value returned by `f` after the predicate has become true.
465 ///
466 /// # Example
467 ///
468 /// ```rust
469 /// use std::{
470 /// sync::Arc,
471 /// thread,
472 /// };
473 ///
474 /// use qubit_lock::ParkingLotMonitor;
475 ///
476 /// let monitor = Arc::new(ParkingLotMonitor::new(false));
477 /// let waiter_monitor = Arc::clone(&monitor);
478 ///
479 /// let waiter = thread::spawn(move || {
480 /// waiter_monitor.wait_until(
481 /// |ready| *ready,
482 /// |ready| {
483 /// *ready = false;
484 /// "done"
485 /// },
486 /// )
487 /// });
488 ///
489 /// monitor.write(|ready| *ready = true);
490 /// monitor.notify_one();
491 ///
492 /// assert_eq!(waiter.join().expect("waiter should finish"), "done");
493 /// ```
494 #[inline]
495 pub fn wait_until<R, P, F>(&self, mut ready: P, f: F) -> R
496 where
497 P: FnMut(&T) -> bool,
498 F: FnOnce(&mut T) -> R,
499 {
500 self.wait_while(|state| !ready(state), f)
501 }
502
503 /// Waits while a predicate remains true, with an overall time limit.
504 ///
505 /// This method is the timeout-aware form of [`Self::wait_while`]. It keeps
506 /// rechecking `waiting` under the monitor lock and waits only for the
507 /// remaining portion of `timeout`. If `waiting` becomes false before the
508 /// timeout expires, `f` runs while the lock is still held. If the timeout
509 /// expires first, the closure is not called.
510 ///
511 /// Timeout status alone is not used as proof that the predicate is still
512 /// true; the predicate is always rechecked under the lock.
513 ///
514 /// # Arguments
515 ///
516 /// * `timeout` - Maximum total duration to wait.
517 /// * `waiting` - Predicate that returns `true` while the caller should
518 /// continue waiting.
519 /// * `f` - Closure that receives mutable access when waiting is no longer
520 /// required.
521 ///
522 /// # Returns
523 ///
524 /// [`WaitTimeoutResult::Ready`] with the value returned by `f` when the
525 /// predicate stops blocking before the timeout. Returns
526 /// [`WaitTimeoutResult::TimedOut`] when the timeout expires first.
527 ///
528 /// # Example
529 ///
530 /// ```rust
531 /// use std::time::Duration;
532 ///
533 /// use qubit_lock::{ParkingLotMonitor, WaitTimeoutResult};
534 ///
535 /// let monitor = ParkingLotMonitor::new(Vec::<i32>::new());
536 /// let result = monitor.wait_while_for(
537 /// Duration::from_millis(1),
538 /// |items| items.is_empty(),
539 /// |items| items.pop(),
540 /// );
541 ///
542 /// assert_eq!(result, WaitTimeoutResult::TimedOut);
543 /// ```
544 #[inline]
545 pub fn wait_while_for<R, P, F>(
546 &self,
547 timeout: Duration,
548 mut waiting: P,
549 f: F,
550 ) -> WaitTimeoutResult<R>
551 where
552 P: FnMut(&T) -> bool,
553 F: FnOnce(&mut T) -> R,
554 {
555 let mut guard = self.lock();
556 let start = Instant::now();
557 loop {
558 if !waiting(&*guard) {
559 return WaitTimeoutResult::Ready(f(&mut *guard));
560 }
561
562 let elapsed = start.elapsed();
563 let remaining = timeout.checked_sub(elapsed).unwrap_or_default();
564 if remaining.is_zero() {
565 return WaitTimeoutResult::TimedOut;
566 }
567
568 let (next_guard, _status) = guard.wait_timeout(remaining);
569 guard = next_guard;
570 }
571 }
572
573 /// Waits until a predicate becomes true, with an overall time limit.
574 ///
575 /// This is the positive-predicate counterpart of
576 /// [`Self::wait_while_for`]. If `ready` becomes true before the timeout
577 /// expires, `f` runs while the monitor lock is still held. If the timeout
578 /// expires first, the closure is not called.
579 ///
580 /// Timeout status alone is not used as proof that the predicate is still
581 /// false; the predicate is always rechecked under the lock.
582 ///
583 /// # Arguments
584 ///
585 /// * `timeout` - Maximum total duration to wait.
586 /// * `ready` - Predicate that returns `true` when the caller may continue.
587 /// * `f` - Closure that receives mutable access to the ready state.
588 ///
589 /// # Returns
590 ///
591 /// [`WaitTimeoutResult::Ready`] with the value returned by `f` when the
592 /// predicate becomes true before the timeout. Returns
593 /// [`WaitTimeoutResult::TimedOut`] when the timeout expires first.
594 ///
595 /// # Example
596 ///
597 /// ```rust
598 /// use std::{
599 /// sync::Arc,
600 /// thread,
601 /// time::Duration,
602 /// };
603 ///
604 /// use qubit_lock::{ParkingLotMonitor, WaitTimeoutResult};
605 ///
606 /// let monitor = Arc::new(ParkingLotMonitor::new(false));
607 /// let waiter_monitor = Arc::clone(&monitor);
608 ///
609 /// let waiter = thread::spawn(move || {
610 /// waiter_monitor.wait_until_for(
611 /// Duration::from_secs(1),
612 /// |ready| *ready,
613 /// |ready| {
614 /// *ready = false;
615 /// 5
616 /// },
617 /// )
618 /// });
619 ///
620 /// monitor.write(|ready| *ready = true);
621 /// monitor.notify_one();
622 ///
623 /// assert_eq!(
624 /// waiter.join().expect("waiter should finish"),
625 /// WaitTimeoutResult::Ready(5),
626 /// );
627 /// ```
628 #[inline]
629 pub fn wait_until_for<R, P, F>(
630 &self,
631 timeout: Duration,
632 mut ready: P,
633 f: F,
634 ) -> WaitTimeoutResult<R>
635 where
636 P: FnMut(&T) -> bool,
637 F: FnOnce(&mut T) -> R,
638 {
639 self.wait_while_for(timeout, |state| !ready(state), f)
640 }
641
642 /// Wakes one thread waiting on this monitor's condition variable.
643 ///
644 /// Notifications do not carry state by themselves. A waiting thread only
645 /// proceeds safely after rechecking the protected state. Call this after
646 /// changing state that may make one waiter able to continue.
647 ///
648 /// # Example
649 ///
650 /// ```rust
651 /// use std::thread;
652 ///
653 /// use qubit_lock::ArcParkingLotMonitor;
654 ///
655 /// let monitor = ArcParkingLotMonitor::new(0_u32);
656 /// let waiter = {
657 /// let m = monitor.clone();
658 /// thread::spawn(move || {
659 /// m.wait_until(|n| *n > 0, |n| {
660 /// *n -= 1;
661 /// });
662 /// })
663 /// };
664 ///
665 /// monitor.write(|n| *n = 1);
666 /// monitor.notify_one();
667 /// waiter.join().expect("waiter should finish");
668 /// ```
669 #[inline]
670 pub fn notify_one(&self) {
671 self.changed.notify_one();
672 }
673
674 /// Wakes all threads waiting on this monitor's condition variable.
675 ///
676 /// Notifications do not carry state by themselves. Every awakened thread
677 /// must recheck the protected state before continuing. Call this after a
678 /// state change that may allow multiple waiters to make progress.
679 ///
680 /// # Example
681 ///
682 /// ```rust
683 /// use std::thread;
684 ///
685 /// use qubit_lock::ArcParkingLotMonitor;
686 ///
687 /// let monitor = ArcParkingLotMonitor::new(false);
688 /// let mut handles = Vec::new();
689 /// for _ in 0..2 {
690 /// let m = monitor.clone();
691 /// handles.push(thread::spawn(move || {
692 /// m.wait_until(|ready| *ready, |_| ());
693 /// }));
694 /// }
695 ///
696 /// monitor.write(|ready| *ready = true);
697 /// monitor.notify_all();
698 /// for h in handles {
699 /// h.join().expect("waiter should finish");
700 /// }
701 /// ```
702 #[inline]
703 pub fn notify_all(&self) {
704 self.changed.notify_all();
705 }
706}
707
708impl<T> Notifier for ParkingLotMonitor<T> {
709 /// Wakes one thread waiting on this monitor.
710 #[inline]
711 fn notify_one(&self) {
712 Self::notify_one(self);
713 }
714
715 /// Wakes all threads waiting on this monitor.
716 #[inline]
717 fn notify_all(&self) {
718 Self::notify_all(self);
719 }
720}
721
722impl<T> NotificationWaiter for ParkingLotMonitor<T> {
723 /// Blocks until a notification wakes this waiter.
724 #[inline]
725 fn wait(&self) {
726 Self::wait(self);
727 }
728}
729
730impl<T> TimeoutNotificationWaiter for ParkingLotMonitor<T> {
731 /// Blocks until a notification wakes this waiter or the timeout expires.
732 #[inline]
733 fn wait_for(&self, timeout: Duration) -> WaitTimeoutStatus {
734 Self::wait_for(self, timeout)
735 }
736}
737
738impl<T> ConditionWaiter for ParkingLotMonitor<T> {
739 type State = T;
740
741 /// Blocks until the predicate becomes true, then runs the action.
742 #[inline]
743 fn wait_until<R, P, F>(&self, predicate: P, action: F) -> R
744 where
745 P: FnMut(&Self::State) -> bool,
746 F: FnOnce(&mut Self::State) -> R,
747 {
748 Self::wait_until(self, predicate, action)
749 }
750
751 /// Blocks while the predicate remains true, then runs the action.
752 #[inline]
753 fn wait_while<R, P, F>(&self, predicate: P, action: F) -> R
754 where
755 P: FnMut(&Self::State) -> bool,
756 F: FnOnce(&mut Self::State) -> R,
757 {
758 Self::wait_while(self, predicate, action)
759 }
760}
761
762impl<T> TimeoutConditionWaiter for ParkingLotMonitor<T> {
763 /// Blocks until the predicate becomes true or the timeout expires.
764 #[inline]
765 fn wait_until_for<R, P, F>(
766 &self,
767 timeout: Duration,
768 predicate: P,
769 action: F,
770 ) -> WaitTimeoutResult<R>
771 where
772 P: FnMut(&Self::State) -> bool,
773 F: FnOnce(&mut Self::State) -> R,
774 {
775 Self::wait_until_for(self, timeout, predicate, action)
776 }
777
778 /// Blocks while the predicate remains true or until the timeout expires.
779 #[inline]
780 fn wait_while_for<R, P, F>(
781 &self,
782 timeout: Duration,
783 predicate: P,
784 action: F,
785 ) -> WaitTimeoutResult<R>
786 where
787 P: FnMut(&Self::State) -> bool,
788 F: FnOnce(&mut Self::State) -> R,
789 {
790 Self::wait_while_for(self, timeout, predicate, action)
791 }
792}
793
794impl<T> From<T> for ParkingLotMonitor<T> {
795 /// Creates a monitor from an initial state value.
796 ///
797 /// # Arguments
798 ///
799 /// * `value` - Initial state protected by the monitor.
800 ///
801 /// # Returns
802 ///
803 /// A monitor initialized with `value`.
804 #[inline]
805 fn from(value: T) -> Self {
806 Self::new(value)
807 }
808}
809
810impl<T: Default> Default for ParkingLotMonitor<T> {
811 /// Creates a monitor containing `T::default()`.
812 ///
813 /// # Returns
814 ///
815 /// A monitor protecting the default value for `T`.
816 ///
817 /// # Example
818 ///
819 /// ```rust
820 /// use qubit_lock::ParkingLotMonitor;
821 ///
822 /// let monitor: ParkingLotMonitor<String> = ParkingLotMonitor::default();
823 /// assert!(monitor.read(|s| s.is_empty()));
824 /// ```
825 #[inline]
826 fn default() -> Self {
827 Self::new(T::default())
828 }
829}