]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/hermit/condvar.rs
Merge commit '3d0b0e66afdfaa519d8855b338b35b4605775945' into clippyup
[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 unsafe impl Send for Condvar {}
18 unsafe impl Sync for Condvar {}
19
20 impl Condvar {
21     pub const fn new() -> Condvar {
22         Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() }
23     }
24
25     pub unsafe fn init(&mut self) {
26         let _ = abi::sem_init(&mut self.sem1 as *mut *const c_void, 0);
27         let _ = abi::sem_init(&mut self.sem2 as *mut *const c_void, 0);
28     }
29
30     pub unsafe fn notify_one(&self) {
31         if self.counter.load(SeqCst) > 0 {
32             self.counter.fetch_sub(1, SeqCst);
33             abi::sem_post(self.sem1);
34             abi::sem_timedwait(self.sem2, 0);
35         }
36     }
37
38     pub unsafe fn notify_all(&self) {
39         let counter = self.counter.swap(0, SeqCst);
40         for _ in 0..counter {
41             abi::sem_post(self.sem1);
42         }
43         for _ in 0..counter {
44             abi::sem_timedwait(self.sem2, 0);
45         }
46     }
47
48     pub unsafe fn wait(&self, mutex: &Mutex) {
49         self.counter.fetch_add(1, SeqCst);
50         mutex.unlock();
51         abi::sem_timedwait(self.sem1, 0);
52         abi::sem_post(self.sem2);
53         mutex.lock();
54     }
55
56     pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
57         panic!("wait_timeout not supported on hermit");
58     }
59
60     pub unsafe fn destroy(&self) {
61         let _ = abi::sem_destroy(self.sem1);
62         let _ = abi::sem_destroy(self.sem2);
63     }
64 }