]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/hermit/condvar.rs
Rollup merge of #76227 - CDirkx:const-poll, r=KodrAus
[rust.git] / library / std / src / sys / hermit / condvar.rs
1 use crate::ffi::c_void;
2 use crate::ptr;
3 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
4 use crate::sys::hermit::abi;
5 use crate::sys::mutex::Mutex;
6 use crate::time::Duration;
7
8 // The implementation is inspired by Andrew D. Birrell's paper
9 // "Implementing Condition Variables with Semaphores"
10
11 pub struct Condvar {
12     counter: AtomicUsize,
13     sem1: *const c_void,
14     sem2: *const c_void,
15 }
16
17 pub type MovableCondvar = Box<Condvar>;
18
19 unsafe impl Send for Condvar {}
20 unsafe impl Sync for Condvar {}
21
22 impl Condvar {
23     pub const fn new() -> Condvar {
24         Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() }
25     }
26
27     pub unsafe fn init(&mut self) {
28         let _ = abi::sem_init(&mut self.sem1 as *mut *const c_void, 0);
29         let _ = abi::sem_init(&mut self.sem2 as *mut *const c_void, 0);
30     }
31
32     pub unsafe fn notify_one(&self) {
33         if self.counter.load(SeqCst) > 0 {
34             self.counter.fetch_sub(1, SeqCst);
35             abi::sem_post(self.sem1);
36             abi::sem_timedwait(self.sem2, 0);
37         }
38     }
39
40     pub unsafe fn notify_all(&self) {
41         let counter = self.counter.swap(0, SeqCst);
42         for _ in 0..counter {
43             abi::sem_post(self.sem1);
44         }
45         for _ in 0..counter {
46             abi::sem_timedwait(self.sem2, 0);
47         }
48     }
49
50     pub unsafe fn wait(&self, mutex: &Mutex) {
51         self.counter.fetch_add(1, SeqCst);
52         mutex.unlock();
53         abi::sem_timedwait(self.sem1, 0);
54         abi::sem_post(self.sem2);
55         mutex.lock();
56     }
57
58     pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
59         panic!("wait_timeout not supported on hermit");
60     }
61
62     pub unsafe fn destroy(&self) {
63         let _ = abi::sem_destroy(self.sem1);
64         let _ = abi::sem_destroy(self.sem2);
65     }
66 }