use core::sync::atomic::{AtomicU16, Ordering};
pub struct Semaphore {
lock: AtomicU16,
}
impl Semaphore {
pub const fn new() -> Self {
Self { lock: AtomicU16::new(0) }
}
pub const fn with_initial_value(value: u16) -> Self {
Self { lock: AtomicU16::new(value) }
}
pub fn try_dec(&self, n: u16) -> Option<()> {
while self.lock.fetch_update(Ordering::Acquire, Ordering::Relaxed, |old| {
if old >= n {
Some(old - n)
} else {
None
}
})
.is_err() { }
Some(())
}
pub fn dec(&self, n: u16) {
loop {
if let Some(guard) = self.try_dec(n) {
return guard
}
core::hint::spin_loop();
}
}
pub fn inc(&self, n: u16) {
self.lock.fetch_add(n, Ordering::Release);
}
pub fn get_value(&self) -> u16 {
self.lock.load(Ordering::Relaxed)
}
}
impl Default for Semaphore {
fn default() -> Self {
Self::new()
}
}