std\sys\pal\windows/
futex.rs1use core::ffi::c_void;
2use core::ptr;
3use core::sync::atomic::{
4 Atomic, AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicPtr,
5 AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
6};
7use core::time::Duration;
8
9use super::api::{self, WinError};
10use crate::sys::{c, dur2timeout};
11
12pub type Futex = Atomic<Primitive>;
14pub type Primitive = u32;
16
17pub type SmallFutex = Atomic<SmallPrimitive>;
19pub type SmallPrimitive = u8;
21
22pub unsafe trait Futexable {}
23pub unsafe trait Waitable {
24 type Futex;
25}
26macro_rules! unsafe_waitable_int {
27 ($(($int:ty, $atomic:ty)),*$(,)?) => {
28 $(
29 unsafe impl Waitable for $int {
30 type Futex = $atomic;
31 }
32 unsafe impl Futexable for $atomic {}
33 )*
34 };
35}
36unsafe_waitable_int! {
37 (bool, AtomicBool),
38 (i8, AtomicI8),
39 (i16, AtomicI16),
40 (i32, AtomicI32),
41 (i64, AtomicI64),
42 (isize, AtomicIsize),
43 (u8, AtomicU8),
44 (u16, AtomicU16),
45 (u32, AtomicU32),
46 (u64, AtomicU64),
47 (usize, AtomicUsize),
48}
49unsafe impl<T> Waitable for *const T {
50 type Futex = Atomic<*mut T>;
51}
52unsafe impl<T> Waitable for *mut T {
53 type Futex = Atomic<*mut T>;
54}
55unsafe impl<T> Futexable for AtomicPtr<T> {}
56
57pub fn wait_on_address<W: Waitable>(
58 address: &W::Futex,
59 compare: W,
60 timeout: Option<Duration>,
61) -> bool {
62 unsafe {
63 let addr = ptr::from_ref(address).cast::<c_void>();
64 let size = size_of::<W>();
65 let compare_addr = (&raw const compare).cast::<c_void>();
66 let timeout = timeout.map(dur2timeout).unwrap_or(c::INFINITE);
67 c::WaitOnAddress(addr, compare_addr, size, timeout) == c::TRUE
68 }
69}
70
71pub fn wake_by_address_single<T: Futexable>(address: &T) {
72 unsafe {
73 let addr = ptr::from_ref(address).cast::<c_void>();
74 c::WakeByAddressSingle(addr);
75 }
76}
77
78pub fn wake_by_address_all<T: Futexable>(address: &T) {
79 unsafe {
80 let addr = ptr::from_ref(address).cast::<c_void>();
81 c::WakeByAddressAll(addr);
82 }
83}
84
85pub fn futex_wait<W: Waitable>(futex: &W::Futex, expected: W, timeout: Option<Duration>) -> bool {
86 wait_on_address(futex, expected, timeout) || api::get_last_error() != WinError::TIMEOUT
88}
89
90pub fn futex_wake<T: Futexable>(futex: &T) -> bool {
91 wake_by_address_single(futex);
92 false
93}
94
95pub fn futex_wake_all<T: Futexable>(futex: &T) {
96 wake_by_address_all(futex)
97}