@@ -4,49 +4,83 @@ use crate::sys::dur2timeout;
44use core:: ffi:: c_void;
55use core:: mem;
66use core:: ptr;
7+ use core:: sync:: atomic:: {
8+ AtomicBool , AtomicI16 , AtomicI32 , AtomicI64 , AtomicI8 , AtomicIsize , AtomicPtr , AtomicU16 ,
9+ AtomicU32 , AtomicU64 , AtomicU8 , AtomicUsize ,
10+ } ;
711use core:: time:: Duration ;
812
9- #[ inline( always) ]
10- pub fn wait_on_address < T , U > ( address : & T , compare : U , timeout : Option < Duration > ) -> bool {
11- assert_eq ! ( mem:: size_of:: <T >( ) , mem:: size_of:: <U >( ) ) ;
13+ pub unsafe trait Waitable {
14+ type Atomic ;
15+ }
16+ macro_rules! unsafe_waitable_int {
17+ ( $( ( $int: ty, $atomic: ty) ) ,* $( , ) ?) => {
18+ $(
19+ unsafe impl Waitable for $int {
20+ type Atomic = $atomic;
21+ }
22+ ) *
23+ } ;
24+ }
25+ unsafe_waitable_int ! {
26+ ( bool , AtomicBool ) ,
27+ ( i8 , AtomicI8 ) ,
28+ ( i16 , AtomicI16 ) ,
29+ ( i32 , AtomicI32 ) ,
30+ ( i64 , AtomicI64 ) ,
31+ ( isize , AtomicIsize ) ,
32+ ( u8 , AtomicU8 ) ,
33+ ( u16 , AtomicU16 ) ,
34+ ( u32 , AtomicU32 ) ,
35+ ( u64 , AtomicU64 ) ,
36+ ( usize , AtomicUsize ) ,
37+ }
38+ unsafe impl < T > Waitable for * const T {
39+ type Atomic = AtomicPtr < T > ;
40+ }
41+ unsafe impl < T > Waitable for * mut T {
42+ type Atomic = AtomicPtr < T > ;
43+ }
44+
45+ pub fn wait_on_address < W : Waitable > (
46+ address : & W :: Atomic ,
47+ compare : W ,
48+ timeout : Option < Duration > ,
49+ ) -> bool {
50+ assert_eq ! ( mem:: size_of:: <W >( ) , mem:: size_of:: <W >( ) ) ;
1251 unsafe {
1352 let addr = ptr:: from_ref ( address) . cast :: < c_void > ( ) ;
14- let size = mem:: size_of :: < T > ( ) ;
53+ let size = mem:: size_of :: < W > ( ) ;
1554 let compare_addr = ptr:: addr_of!( compare) . cast :: < c_void > ( ) ;
1655 let timeout = timeout. map ( dur2timeout) . unwrap_or ( c:: INFINITE ) ;
1756 c:: WaitOnAddress ( addr, compare_addr, size, timeout) == c:: TRUE
1857 }
1958}
2059
21- #[ inline( always) ]
2260pub fn wake_by_address_single < T > ( address : & T ) {
2361 unsafe {
2462 let addr = ptr:: from_ref ( address) . cast :: < c_void > ( ) ;
2563 c:: WakeByAddressSingle ( addr) ;
2664 }
2765}
2866
29- #[ inline( always) ]
3067pub fn wake_by_address_all < T > ( address : & T ) {
3168 unsafe {
3269 let addr = ptr:: from_ref ( address) . cast :: < c_void > ( ) ;
3370 c:: WakeByAddressAll ( addr) ;
3471 }
3572}
3673
37- #[ inline( always) ]
38- pub fn futex_wait < T , U > ( futex : & T , expected : U , timeout : Option < Duration > ) -> bool {
74+ pub fn futex_wait < W : Waitable > ( futex : & W :: Atomic , expected : W , timeout : Option < Duration > ) -> bool {
3975 // return false only on timeout
4076 wait_on_address ( futex, expected, timeout) || api:: get_last_error ( ) . code != c:: ERROR_TIMEOUT
4177}
4278
43- #[ inline( always) ]
4479pub fn futex_wake < T > ( futex : & T ) -> bool {
4580 wake_by_address_single ( futex) ;
4681 false
4782}
4883
49- #[ inline( always) ]
5084pub fn futex_wake_all < T > ( futex : & T ) {
5185 wake_by_address_all ( futex)
5286}
0 commit comments