74 lines
1.6 KiB
Rust
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();
|
|
}
|
|
}
|