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
}
}
|