diff options
| author | Chris Denton <chris@chrisdenton.dev> | 2024-03-05 18:44:46 +0000 |
|---|---|---|
| committer | Chris Denton <chris@chrisdenton.dev> | 2024-03-05 20:48:48 +0000 |
| commit | cf83d83c77eb9c5a08debc818156815ae5bf759f (patch) | |
| tree | bb3928411db014ae3748ac86bc58ddfc2ef2df81 | |
| parent | 2a098577294333ad3c5492a1935aa1d653e70c9b (diff) | |
| download | rust-cf83d83c77eb9c5a08debc818156815ae5bf759f.tar.gz rust-cf83d83c77eb9c5a08debc818156815ae5bf759f.zip | |
Add `Waitable` trait
| -rw-r--r-- | library/std/src/sys/pal/windows/futex.rs | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs index 88f20ed270b..bc19c402d9c 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<T, U>(address: &T, compare: U, timeout: Option<Duration>) -> bool { - assert_eq!(mem::size_of::<T>(), mem::size_of::<U>()); +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<T> Waitable for *const T { + type Atomic = AtomicPtr<T>; +} +unsafe impl<T> Waitable for *mut T { + type Atomic = AtomicPtr<T>; +} + +pub fn wait_on_address<W: Waitable>( + address: &W::Atomic, + compare: W, + timeout: Option<Duration>, +) -> bool { unsafe { let addr = ptr::from_ref(address).cast::<c_void>(); - let size = mem::size_of::<T>(); + let size = mem::size_of::<W>(); let compare_addr = ptr::addr_of!(compare).cast::<c_void>(); 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<T>(address: &T) { unsafe { let addr = ptr::from_ref(address).cast::<c_void>(); @@ -26,7 +63,6 @@ pub fn wake_by_address_single<T>(address: &T) { } } -#[inline(always)] pub fn wake_by_address_all<T>(address: &T) { unsafe { let addr = ptr::from_ref(address).cast::<c_void>(); @@ -34,19 +70,16 @@ pub fn wake_by_address_all<T>(address: &T) { } } -#[inline(always)] -pub fn futex_wait<T, U>(futex: &T, expected: U, timeout: Option<Duration>) -> bool { +pub fn futex_wait<W: Waitable>(futex: &W::Atomic, expected: W, timeout: Option<Duration>) -> 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<T>(futex: &T) -> bool { wake_by_address_single(futex); false } -#[inline(always)] pub fn futex_wake_all<T>(futex: &T) { wake_by_address_all(futex) } |
