diff options
| author | Mica White <botahamec@outlook.com> | 2025-12-08 20:14:03 -0500 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2025-12-08 20:14:03 -0500 |
| commit | c31f4ce84c3c8b3f89a05890df775d4e766aaadb (patch) | |
| tree | 40169c1240717002197c85985f9bb652dd4b0af8 /src/futex/windows.rs | |
Diffstat (limited to 'src/futex/windows.rs')
| -rwxr-xr-x | src/futex/windows.rs | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/src/futex/windows.rs b/src/futex/windows.rs new file mode 100755 index 0000000..153d9ef --- /dev/null +++ b/src/futex/windows.rs @@ -0,0 +1,114 @@ +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::<Atomic>(); + let addr = core::ptr::from_ref(&self.0).cast::<c_void>(); + let compare_addr = ptr::addr_of!(compare).cast::<c_void>(); + WaitOnAddress(addr, expected_start_value, SIZE, INFINITE); + } + + #[inline] + pub fn wake(&self) -> bool { + WakeByAddressSingle(core::ptr::from_ref(&self.0).cast::<c_void>()); + false + } + + #[inline] + pub fn wake_all(&self) { + unsafe { + let addr = core::ptr::from_ref(address).cast::<c_void>(); + 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::<SmallAtomic>(); + let addr = core::ptr::from_ref(&self.0).cast::<c_void>(); + let compare_addr = ptr::addr_of!(compare).cast::<c_void>(); + WaitOnAddress(addr, expected_start_value, SIZE, INFINITE); + } + + #[inline] + pub fn wake(&self) -> bool { + WakeByAddressSingle(core::ptr::from_ref(&self.0).cast::<c_void>()); + false + } + + #[inline] + pub fn wake_all(&self) { + unsafe { + let addr = core::ptr::from_ref(address).cast::<c_void>(); + WakeByAddressAll(addr); + } + } +} + +impl Deref for SmallFutex { + type Target = SmallAtomic; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} |
