rt/rust/src/sync/condvar.rs

74 lines
1.6 KiB
Rust

use core::{
cell::UnsafeCell,
marker::PhantomPinned,
panic::{RefUnwindSafe, UnwindSafe},
};
use crate::{
bindings::{rt_cond, rt_cond_broadcast, rt_cond_signal, rt_cond_timedwait, rt_cond_wait},
sync::{semaphore::c_sem_init, MutexGuard},
tick::Utick,
};
pub struct Condvar {
c: UnsafeCell<rt_cond>,
_pin_marker: PhantomPinned,
}
unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {}
impl UnwindSafe for Condvar {}
impl RefUnwindSafe for Condvar {}
impl Condvar {
pub const fn init(cond: &'static Condvar) -> Condvar {
let c = unsafe { &*(cond.c.get() as *const rt_cond) };
Condvar {
c: UnsafeCell::new(rt_cond {
sem: c_sem_init(&c.sem, 0, 0),
}),
_pin_marker: PhantomPinned,
}
}
pub fn signal(&self) {
unsafe { rt_cond_signal(self.c.get()) }
}
pub fn broadcast(&self) {
unsafe { rt_cond_broadcast(self.c.get()) }
}
pub fn wait<T>(&self, guard: &MutexGuard<T>) {
unsafe { rt_cond_wait(self.c.get(), guard.ptr()) }
}
pub fn timedwait<'a, T>(
&self,
guard: MutexGuard<'a, T>,
ticks: Utick,
) -> Option<MutexGuard<'a, T>> {
if unsafe { rt_cond_timedwait(self.c.get(), guard.ptr(), ticks) } {
Some(guard)
} else {
None
}
}
}
#[macro_export]
macro_rules! condvar {
($name: ident) => {
static $name: $crate::sync::Condvar = $crate::sync::Condvar::init(&$name);
};
}
#[cfg(test)]
mod tests {
#[test]
fn signal() {
condvar!(CONDVAR);
CONDVAR.signal();
}
}