1use crate::sync::atomic::Ordering::Relaxed;
2use crate::sys::futex::{Futex, futex_wait, futex_wake, futex_wake_all};
3use crate::sys::sync::Mutex;
4use crate::time::Duration;
56pub struct Condvar {
7// The value of this atomic is simply incremented on every notification.
8 // This is used by `.wait()` to not miss any notifications after
9 // unlocking the mutex and before waiting for notifications.
10futex: Futex,
11}
1213impl Condvar {
14#[inline]
15pub const fn new() -> Self {
16Self { futex: Futex::new(0) }
17 }
1819// All the memory orderings here are `Relaxed`,
20 // because synchronization is done by unlocking and locking the mutex.
2122pub fn notify_one(&self) {
23self.futex.fetch_add(1, Relaxed);
24 futex_wake(&self.futex);
25 }
2627pub fn notify_all(&self) {
28self.futex.fetch_add(1, Relaxed);
29 futex_wake_all(&self.futex);
30 }
3132pub unsafe fn wait(&self, mutex: &Mutex) {
33self.wait_optional_timeout(mutex, None);
34 }
3536pub unsafe fn wait_timeout(&self, mutex: &Mutex, timeout: Duration) -> bool {
37self.wait_optional_timeout(mutex, Some(timeout))
38 }
3940unsafe fn wait_optional_timeout(&self, mutex: &Mutex, timeout: Option<Duration>) -> bool {
41// Examine the notification counter _before_ we unlock the mutex.
42let futex_value = self.futex.load(Relaxed);
4344// Unlock the mutex before going to sleep.
45mutex.unlock();
4647// Wait, but only if there hasn't been any
48 // notification since we unlocked the mutex.
49let r = futex_wait(&self.futex, futex_value, timeout);
5051// Lock the mutex again.
52mutex.lock();
5354 r
55 }
56}