]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/hermit/condvar.rs
662dc9394a36f228a24bee1313b3619a9ebe6afc
[rust.git] / library / std / src / sys / hermit / condvar.rs
1 #![deny(unsafe_op_in_unsafe_fn)]
2
3 use crate::ffi::c_void;
4 use crate::ptr;
5 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
6 use crate::sys::hermit::abi;
7 use crate::sys::mutex::Mutex;
8 use crate::time::Duration;
9
10 // The implementation is inspired by Andrew D. Birrell's paper
11 // "Implementing Condition Variables with Semaphores"
12
13 pub struct Condvar {
14     counter: AtomicUsize,
15     sem1: *const c_void,
16     sem2: *const c_void,
17 }
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         unsafe {
29             let _ = abi::sem_init(&mut self.sem1 as *mut *const c_void, 0);
30             let _ = abi::sem_init(&mut self.sem2 as *mut *const c_void, 0);
31         }
32     }
33
34     pub unsafe fn notify_one(&self) {
35         if self.counter.load(SeqCst) > 0 {
36             self.counter.fetch_sub(1, SeqCst);
37             unsafe {
38                 abi::sem_post(self.sem1);
39                 abi::sem_timedwait(self.sem2, 0);
40             }
41         }
42     }
43
44     pub unsafe fn notify_all(&self) {
45         let counter = self.counter.swap(0, SeqCst);
46         for _ in 0..counter {
47             unsafe {
48                 abi::sem_post(self.sem1);
49             }
50         }
51         for _ in 0..counter {
52             unsafe {
53                 abi::sem_timedwait(self.sem2, 0);
54             }
55         }
56     }
57
58     pub unsafe fn wait(&self, mutex: &Mutex) {
59         self.counter.fetch_add(1, SeqCst);
60         mutex.unlock();
61         unsafe {
62             abi::sem_timedwait(self.sem1, 0);
63             abi::sem_post(self.sem2);
64         }
65         mutex.lock();
66     }
67
68     pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
69         panic!("wait_timeout not supported on hermit");
70     }
71
72     pub unsafe fn destroy(&self) {
73         unsafe {
74             let _ = abi::sem_destroy(self.sem1);
75             let _ = abi::sem_destroy(self.sem2);
76         }
77     }
78 }