diff options
| author | joboet <jonasboettiger@icloud.com> | 2024-03-12 14:55:06 +0100 |
|---|---|---|
| committer | joboet <jonasboettiger@icloud.com> | 2024-03-12 15:41:06 +0100 |
| commit | 22a5267c83a3e17f2b763279eb24bb632c45dc6b (patch) | |
| tree | 81eca4925b77ec92b4f2fd66962af948fe59d094 /library/std/src/sys/sync/condvar/futex.rs | |
| parent | 3b85d2c7fc6d1698e68b94f7bc1a5c9633f2554d (diff) | |
| download | rust-22a5267c83a3e17f2b763279eb24bb632c45dc6b.tar.gz rust-22a5267c83a3e17f2b763279eb24bb632c45dc6b.zip | |
std: move `Once` implementations to `sys`
Diffstat (limited to 'library/std/src/sys/sync/condvar/futex.rs')
| -rw-r--r-- | library/std/src/sys/sync/condvar/futex.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/library/std/src/sys/sync/condvar/futex.rs b/library/std/src/sys/sync/condvar/futex.rs new file mode 100644 index 00000000000..4586d0fd941 --- /dev/null +++ b/library/std/src/sys/sync/condvar/futex.rs @@ -0,0 +1,56 @@ +use crate::sync::atomic::{AtomicU32, Ordering::Relaxed}; +use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; +use crate::sys::sync::Mutex; +use crate::time::Duration; + +pub struct Condvar { + // The value of this atomic is simply incremented on every notification. + // This is used by `.wait()` to not miss any notifications after + // unlocking the mutex and before waiting for notifications. + futex: AtomicU32, +} + +impl Condvar { + #[inline] + pub const fn new() -> Self { + Self { futex: AtomicU32::new(0) } + } + + // All the memory orderings here are `Relaxed`, + // because synchronization is done by unlocking and locking the mutex. + + pub fn notify_one(&self) { + self.futex.fetch_add(1, Relaxed); + futex_wake(&self.futex); + } + + pub fn notify_all(&self) { + self.futex.fetch_add(1, Relaxed); + futex_wake_all(&self.futex); + } + + pub unsafe fn wait(&self, mutex: &Mutex) { + self.wait_optional_timeout(mutex, None); + } + + pub unsafe fn wait_timeout(&self, mutex: &Mutex, timeout: Duration) -> bool { + self.wait_optional_timeout(mutex, Some(timeout)) + } + + unsafe fn wait_optional_timeout(&self, mutex: &Mutex, timeout: Option<Duration>) -> bool { + // Examine the notification counter _before_ we unlock the mutex. + let futex_value = self.futex.load(Relaxed); + + // Unlock the mutex before going to sleep. + mutex.unlock(); + + // Wait, but only if there hasn't been any + // notification since we unlocked the mutex. + let r = futex_wait(&self.futex, futex_value, timeout); + + // Lock the mutex again. + mutex.lock(); + + r + } +} |
