Skip to main content

forge/os/
condvar.rs

1use core::{cell::UnsafeCell, time::Duration};
2
3use sys::os::{TimeSpanType, condvar::*};
4
5use crate::os::mutex::Mutex;
6
7/// A condition variable for blocking threads until a condition becomes true.
8///
9/// Always used together with a [`Mutex`]: callers hold the mutex while checking
10/// the condition, then pass it to [`wait`](Self::wait) so the lock is released
11/// atomically while the thread sleeps.
12pub struct ConditionVariable {
13    inner: UnsafeCell<ConditionVariableType>,
14}
15
16impl ConditionVariable {
17    /// Creates a new condition variable.
18    pub fn new() -> Self {
19        let mut inner = ConditionVariableType::default();
20        unsafe { nnosInitializeConditionVariable(&mut inner as *mut ConditionVariableType) };
21        Self {
22            inner: UnsafeCell::new(inner),
23        }
24    }
25
26    /// Destroys the condition variable. Called automatically on drop.
27    pub fn finalize(&self) {
28        unsafe { nnosFinalizeConditionVariable(self.ptr()) };
29    }
30
31    /// Wakes one thread waiting on this condition variable.
32    pub fn signal(&self) {
33        unsafe { nnosSignalConditionVariable(self.ptr()) };
34    }
35
36    /// Wakes all threads waiting on this condition variable.
37    pub fn broadcast(&self) {
38        unsafe { nnosBroadcastConditionVariable(self.ptr()) };
39    }
40
41    /// Atomically releases `mutex` and blocks until signaled, then reacquires `mutex`.
42    pub fn wait(&self, mutex: &Mutex) {
43        unsafe { nnosWaitConditionVariable(self.ptr(), mutex.ptr()) };
44    }
45
46    /// Like [`wait`](Self::wait), but returns after at most `timeout`. Returns the wait status.
47    pub fn wait_timeout(&self, mutex: &Mutex, timeout: Duration) -> ConditionVariableStatus {
48        let timeout = timeout.as_nanos() as u64;
49        unsafe { nnosTimedWaitConditionVariable(self.ptr(), mutex.ptr(), TimeSpanType(timeout)) }
50    }
51
52    pub(crate) fn ptr(&self) -> *mut ConditionVariableType {
53        self.inner.get()
54    }
55}
56
57impl Drop for ConditionVariable {
58    fn drop(&mut self) {
59        self.finalize();
60    }
61}