use core::ffi::c_void; #[cfg(not(target_vendor = "win7"))] // Use raw-dylib to import synchronization functions to workaround issues with the older mingw import library. #[cfg_attr( target_arch = "x86", link( name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib", import_name_type = "undecorated" ) )] #[cfg_attr( not(target_arch = "x86"), link(name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib") )] extern "system" { type BOOL = i32; pub const TRUE: BOOL = 1; pub const INFINITE: u32 = 4294967295; pub fn WaitOnAddress( address: *const c_void, compareaddress: *const c_void, addresssize: usize, dwmilliseconds: u32, ) -> BOOL; pub fn WakeByAddressSingle(address: *const c_void); pub fn WakeByAddressAll(address: *const c_void); } pub struct Futex(AtomicU32); pub type Primitive = u32; impl Futex { #[inline] pub const fn new(initial_value: Primitive) -> Self { Self(AtomicU32::new(initial_value)) } #[inline] pub fn wait(&self, expected_start_value: Primitive) { const SIZE: u32 = core::mem::size_of::(); let addr = core::ptr::from_ref(&self.0).cast::(); let compare_addr = ptr::addr_of!(compare).cast::(); WaitOnAddress(addr, expected_start_value, SIZE, INFINITE); } #[inline] pub fn wake(&self) -> bool { WakeByAddressSingle(core::ptr::from_ref(&self.0).cast::()); false } #[inline] pub fn wake_all(&self) { unsafe { let addr = core::ptr::from_ref(address).cast::(); WakeByAddressAll(addr); } } } impl Deref for Futex { type Target = Atomic; #[inline] fn deref(&self) -> &Self::Target { &self.0 } } pub struct SmallFutex(AtomicU8); pub type SmallAtomic = AtomicU8; pub type SmallPrimitive = u8; impl SmallFutex { #[inline] pub const fn new(initial_value: SmallPrimitive) -> Self { Self(AtomicU32::new(initial_value)) } #[inline] pub fn wait(&self, expected_start_value: SmallPrimitive) { const SIZE: u32 = core::mem::size_of::(); let addr = core::ptr::from_ref(&self.0).cast::(); let compare_addr = ptr::addr_of!(compare).cast::(); WaitOnAddress(addr, expected_start_value, SIZE, INFINITE); } #[inline] pub fn wake(&self) -> bool { WakeByAddressSingle(core::ptr::from_ref(&self.0).cast::()); false } #[inline] pub fn wake_all(&self) { unsafe { let addr = core::ptr::from_ref(address).cast::(); WakeByAddressAll(addr); } } } impl Deref for SmallFutex { type Target = SmallAtomic; #[inline] fn deref(&self) -> &Self::Target { &self.0 } }