diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs index 88f20ed270baa..bc19c402d9c12 100644 --- a/library/std/src/sys/pal/windows/futex.rs +++ b/library/std/src/sys/pal/windows/futex.rs @@ -4,21 +4,58 @@ use crate::sys::dur2timeout; use core::ffi::c_void; use core::mem; use core::ptr; +use core::sync::atomic::{ + AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, + AtomicU32, AtomicU64, AtomicU8, AtomicUsize, +}; use core::time::Duration; -#[inline(always)] -pub fn wait_on_address(address: &T, compare: U, timeout: Option) -> bool { - assert_eq!(mem::size_of::(), mem::size_of::()); +pub unsafe trait Waitable { + type Atomic; +} +macro_rules! unsafe_waitable_int { + ($(($int:ty, $atomic:ty)),*$(,)?) => { + $( + unsafe impl Waitable for $int { + type Atomic = $atomic; + } + )* + }; +} +unsafe_waitable_int! { + (bool, AtomicBool), + (i8, AtomicI8), + (i16, AtomicI16), + (i32, AtomicI32), + (i64, AtomicI64), + (isize, AtomicIsize), + (u8, AtomicU8), + (u16, AtomicU16), + (u32, AtomicU32), + (u64, AtomicU64), + (usize, AtomicUsize), +} +unsafe impl Waitable for *const T { + type Atomic = AtomicPtr; +} +unsafe impl Waitable for *mut T { + type Atomic = AtomicPtr; +} + +pub fn wait_on_address( + address: &W::Atomic, + compare: W, + timeout: Option, +) -> bool { unsafe { let addr = ptr::from_ref(address).cast::(); - let size = mem::size_of::(); + let size = mem::size_of::(); let compare_addr = ptr::addr_of!(compare).cast::(); let timeout = timeout.map(dur2timeout).unwrap_or(c::INFINITE); c::WaitOnAddress(addr, compare_addr, size, timeout) == c::TRUE } } -#[inline(always)] pub fn wake_by_address_single(address: &T) { unsafe { let addr = ptr::from_ref(address).cast::(); @@ -26,7 +63,6 @@ pub fn wake_by_address_single(address: &T) { } } -#[inline(always)] pub fn wake_by_address_all(address: &T) { unsafe { let addr = ptr::from_ref(address).cast::(); @@ -34,19 +70,16 @@ pub fn wake_by_address_all(address: &T) { } } -#[inline(always)] -pub fn futex_wait(futex: &T, expected: U, timeout: Option) -> bool { +pub fn futex_wait(futex: &W::Atomic, expected: W, timeout: Option) -> bool { // return false only on timeout wait_on_address(futex, expected, timeout) || api::get_last_error().code != c::ERROR_TIMEOUT } -#[inline(always)] pub fn futex_wake(futex: &T) -> bool { wake_by_address_single(futex); false } -#[inline(always)] pub fn futex_wake_all(futex: &T) { wake_by_address_all(futex) }