xref: /aosp_15_r20/external/crosvm/common/sync/src/condvar.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::fmt;
6 use std::fmt::Debug;
7 use std::sync::Condvar as StdCondvar;
8 use std::sync::MutexGuard;
9 use std::sync::WaitTimeoutResult;
10 use std::time::Duration;
11 
12 static CONDVAR_POISONED: &str = "condvar is poisoned";
13 
14 /// A Condition Variable.
15 #[derive(Default)]
16 pub struct Condvar {
17     std: StdCondvar,
18 }
19 
20 impl Condvar {
21     /// Creates a new condvar that is ready to be waited on.
new() -> Condvar22     pub const fn new() -> Condvar {
23         Condvar {
24             std: StdCondvar::new(),
25         }
26     }
27 
28     /// Waits on a condvar, blocking the current thread until it is notified.
wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T>29     pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
30         self.std.wait(guard).expect(CONDVAR_POISONED)
31     }
32 
33     /// Blocks the current thread until this condition variable receives a notification and the
34     /// provided condition is false.
wait_while<'a, T, F>(&self, guard: MutexGuard<'a, T>, condition: F) -> MutexGuard<'a, T> where F: FnMut(&mut T) -> bool,35     pub fn wait_while<'a, T, F>(&self, guard: MutexGuard<'a, T>, condition: F) -> MutexGuard<'a, T>
36     where
37         F: FnMut(&mut T) -> bool,
38     {
39         self.std
40             .wait_while(guard, condition)
41             .expect(CONDVAR_POISONED)
42     }
43 
44     /// Waits on a condvar, blocking the current thread until it is notified
45     /// or the specified duration has elapsed.
wait_timeout<'a, T>( &self, guard: MutexGuard<'a, T>, dur: Duration, ) -> (MutexGuard<'a, T>, WaitTimeoutResult)46     pub fn wait_timeout<'a, T>(
47         &self,
48         guard: MutexGuard<'a, T>,
49         dur: Duration,
50     ) -> (MutexGuard<'a, T>, WaitTimeoutResult) {
51         self.std.wait_timeout(guard, dur).expect(CONDVAR_POISONED)
52     }
53 
54     /// Waits on this condition variable for a notification, timing out after a specified duration.
wait_timeout_while<'a, T, F>( &self, guard: MutexGuard<'a, T>, dur: Duration, condition: F, ) -> (MutexGuard<'a, T>, WaitTimeoutResult) where F: FnMut(&mut T) -> bool,55     pub fn wait_timeout_while<'a, T, F>(
56         &self,
57         guard: MutexGuard<'a, T>,
58         dur: Duration,
59         condition: F,
60     ) -> (MutexGuard<'a, T>, WaitTimeoutResult)
61     where
62         F: FnMut(&mut T) -> bool,
63     {
64         self.std
65             .wait_timeout_while(guard, dur, condition)
66             .expect(CONDVAR_POISONED)
67     }
68 
69     /// Notifies one thread blocked by this condvar.
notify_one(&self)70     pub fn notify_one(&self) {
71         self.std.notify_one();
72     }
73 
74     /// Notifies all threads blocked by this condvar.
notify_all(&self)75     pub fn notify_all(&self) {
76         self.std.notify_all();
77     }
78 }
79 
80 impl Debug for Condvar {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result81     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
82         Debug::fmt(&self.std, formatter)
83     }
84 }
85