ndsd_playback/
semaphore.rs1use std::sync::{
2 atomic::{AtomicUsize, Ordering},
3 Condvar, Mutex,
4};
5
6pub struct Semaphore {
7 permits: AtomicUsize,
8 blocker: Condvar,
10 signal: Mutex<()>,
11}
12
13impl Semaphore {
14 pub const fn new(initial: usize) -> Self {
15 Self {
16 permits: AtomicUsize::new(initial),
17 blocker: Condvar::new(),
18 signal: Mutex::new(()),
19 }
20 }
21
22 pub fn acquire(&self) {
23 loop {
24 let current = self.permits.load(Ordering::Acquire);
26 if current > 0 {
27 if self.permits
28 .compare_exchange(current, current - 1, Ordering::AcqRel, Ordering::Relaxed)
29 .is_ok()
30 {
31 return;
32 }
33 }
34
35 let guard = self.signal.lock().unwrap();
37 let _unused = self.blocker.wait(guard).unwrap();
39 }
40 }
41
42 pub fn release(&self) {
43 self.permits.fetch_add(1, Ordering::Release);
44 self.blocker.notify_one();
46 }
47}