os_sync/sem/
win32.rs

1use core::ptr;
2use core::ffi::c_void;
3
4const WAIT_OBJECT_0: u32 = 0;
5const WAIT_TIMEOUT: u32 = 0x00000102;
6const INFINITE: u32 = 0xFFFFFFFF;
7
8extern "system" {
9    fn CloseHandle(handle: *mut c_void) -> i32;
10    fn CreateSemaphoreW(attrs: *mut c_void, initial: i32, max: i32, name: *const u16) -> *mut c_void;
11    fn WaitForSingleObject(handle: *mut c_void, timeout_ms: u32) -> u32;
12    fn ReleaseSemaphore(handle: *mut c_void, increment: i32, previous_increment: *mut i32) -> i32;
13}
14
15///Windows implementation of Semaphore
16pub struct Sem {
17    handle: *mut c_void
18}
19
20impl super::Semaphore for Sem {
21    fn new(init: u32) -> Option<Self> {
22        let handle = unsafe {
23            CreateSemaphoreW(ptr::null_mut(), init as i32, i32::max_value(), ptr::null())
24        };
25
26        if handle.is_null() {
27            return None;
28        } else {
29            Some(Self {
30                handle
31            })
32        }
33    }
34
35    fn wait(&self) {
36        let result = unsafe {
37            WaitForSingleObject(self.handle, INFINITE)
38        };
39
40        match result {
41            WAIT_OBJECT_0 => (),
42            //We cannot really timeout when there is no timeout
43            other => panic!("Unexpected result: {}", other),
44        }
45    }
46
47    #[inline]
48    fn try_wait(&self) -> bool {
49        self.wait_timeout(core::time::Duration::from_secs(0))
50    }
51
52    fn wait_timeout(&self, timeout: core::time::Duration) -> bool {
53        use core::convert::TryInto;
54
55        let result = unsafe {
56            WaitForSingleObject(self.handle, timeout.as_secs().try_into().unwrap_or(u32::max_value()))
57        };
58
59        match result {
60            WAIT_OBJECT_0 => true,
61            WAIT_TIMEOUT => false,
62            other => panic!("Unexpected result: {}", other),
63        }
64    }
65
66    fn signal(&self) {
67        let res = unsafe {
68            ReleaseSemaphore(self.handle, 1, ptr::null_mut())
69        };
70        debug_assert_ne!(res, 0);
71    }
72
73    fn post(&self) -> bool {
74        let mut prev = 0;
75        let res = unsafe {
76            ReleaseSemaphore(self.handle, 1, &mut prev)
77        };
78
79        debug_assert_ne!(res, 0);
80        prev == 0
81    }
82}
83
84impl Drop for Sem {
85    fn drop(&mut self) {
86        unsafe {
87            CloseHandle(self.handle);
88        }
89    }
90}
91
92unsafe impl Send for Sem {}
93unsafe impl Sync for Sem {}