Skip to content

Commit b946916

Browse files
committed
Add u64 wait & wake variants
1 parent d1b8188 commit b946916

File tree

3 files changed

+86
-3
lines changed

3 files changed

+86
-3
lines changed

src/lib.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![no_std]
22
#![doc = include_str!("../README.md")]
33

4-
use core::sync::atomic::{AtomicPtr, AtomicU32};
4+
use core::sync::atomic::{AtomicPtr, AtomicU32, AtomicU64};
55

66
#[cfg(any(target_os = "linux", target_os = "android"))]
77
#[path = "linux.rs"]
@@ -28,6 +28,15 @@ pub fn wait(atomic: &AtomicU32, value: u32) {
2828
platform::wait(atomic, value)
2929
}
3030

31+
/// If the value is `value`, wait until woken up.
32+
///
33+
/// This function might also return spuriously,
34+
/// without a corresponding wake operation.
35+
#[inline]
36+
pub fn wait_u64(atomic: &AtomicU64, value: u64) {
37+
platform::wait_u64(atomic, value)
38+
}
39+
3140
/// If the value is `value`, wait until woken up.
3241
///
3342
/// This function might also return spuriously,
@@ -44,6 +53,14 @@ pub fn wake_one(atomic: *const AtomicU32) {
4453
platform::wake_one(atomic);
4554
}
4655

56+
/// Wake one thread that is waiting on this atomic.
57+
///
58+
/// It's okay if the pointer dangles or is null.
59+
#[inline]
60+
pub fn wake_one_u64(atomic: *const AtomicU64) {
61+
platform::wake_one_u64(atomic);
62+
}
63+
4764
/// Wake one thread that is waiting on this atomic.
4865
///
4966
/// It's okay if the pointer dangles or is null.
@@ -60,6 +77,14 @@ pub fn wake_all(atomic: *const AtomicU32) {
6077
platform::wake_all(atomic);
6178
}
6279

80+
/// Wake all threads that are waiting on this atomic.
81+
///
82+
/// It's okay if the pointer dangles or is null.
83+
#[inline]
84+
pub fn wake_all_u64(atomic: *const AtomicU64) {
85+
platform::wake_all_u64(atomic);
86+
}
87+
6388
/// Wake all threads that are waiting on this atomic.
6489
///
6590
/// It's okay if the pointer dangles or is null.

src/windows.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::sync::atomic::{AtomicPtr, AtomicU32};
1+
use core::sync::atomic::{AtomicPtr, AtomicU32, AtomicU64};
22
use windows_sys::Win32::System::{
33
Threading::{WaitOnAddress, WakeByAddressAll, WakeByAddressSingle},
44
WindowsProgramming::INFINITE,
@@ -11,6 +11,14 @@ pub fn wait(a: &AtomicU32, expected: u32) {
1111
unsafe { WaitOnAddress(ptr.cast(), expected_ptr.cast(), 4, INFINITE) };
1212
}
1313

14+
#[inline]
15+
pub fn wait_u64(a: &AtomicU64, expected: u64) {
16+
let ptr: *const AtomicU64 = a;
17+
let expected_ptr: *const u64 = &expected;
18+
unsafe { WaitOnAddress(ptr.cast(), expected_ptr.cast(), 4, INFINITE) };
19+
}
20+
21+
#[inline]
1422
pub fn wait_ptr<T>(a: *const AtomicPtr<T>, expected: *const T) {
1523
let expected_ptr: *const *const T = &expected as _;
1624
unsafe { WaitOnAddress(a.cast(), expected_ptr.cast(), 8, INFINITE )};
@@ -21,6 +29,11 @@ pub fn wake_one(ptr: *const AtomicU32) {
2129
unsafe { WakeByAddressSingle(ptr.cast()) };
2230
}
2331

32+
#[inline]
33+
pub fn wake_one_u64(ptr: *const AtomicU64) {
34+
unsafe { WakeByAddressSingle(ptr.cast()) };
35+
}
36+
2437
#[inline]
2538
pub fn wake_one_ptr<T>(ptr: *const AtomicPtr<T>) {
2639
unsafe { WakeByAddressSingle(ptr.cast()) };
@@ -31,6 +44,11 @@ pub fn wake_all(ptr: *const AtomicU32) {
3144
unsafe { WakeByAddressAll(ptr.cast()) };
3245
}
3346

47+
#[inline]
48+
pub fn wake_all_u64(ptr: *const AtomicU64) {
49+
unsafe { WakeByAddressAll(ptr.cast()) };
50+
}
51+
3452
#[inline]
3553
pub fn wake_all_ptr<T>(ptr: *const AtomicPtr<T>) {
3654
unsafe { WakeByAddressAll(ptr.cast()) };

tests/test.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,37 @@
1-
use atomic_wait::{wait, wake_all, wake_one};
1+
use atomic_wait::{wait, wait_u64, wake_all, wake_all_u64, wake_one, wake_one_u64};
22
use std::{
33
sync::atomic::{AtomicU32, Ordering::Relaxed},
44
thread::sleep,
55
time::{Duration, Instant},
66
};
7+
use std::sync::atomic::AtomicU64;
78

89
#[test]
910
fn wake_null() {
1011
wake_one(std::ptr::null::<AtomicU32>());
1112
wake_all(std::ptr::null::<AtomicU32>());
1213
}
1314

15+
#[test]
16+
fn wake_null_u64() {
17+
wake_one_u64(std::ptr::null::<AtomicU64>());
18+
wake_all_u64(std::ptr::null::<AtomicU64>());
19+
}
20+
1421
#[test]
1522
fn wake_nothing() {
1623
let a = AtomicU32::new(0);
1724
wake_one(&a);
1825
wake_all(&a);
1926
}
2027

28+
#[test]
29+
fn wake_nothing_u64() {
30+
let a = AtomicU64::new(0);
31+
wake_one_u64(&a);
32+
wake_all_u64(&a);
33+
}
34+
2135
#[test]
2236
fn wait_unexpected() {
2337
let t = Instant::now();
@@ -26,6 +40,14 @@ fn wait_unexpected() {
2640
assert!(t.elapsed().as_millis() < 100);
2741
}
2842

43+
#[test]
44+
fn wait_unexpected_u64() {
45+
let t = Instant::now();
46+
let a = AtomicU64::new(0);
47+
wait_u64(&a, 1);
48+
assert!(t.elapsed().as_millis() < 100);
49+
}
50+
2951
#[test]
3052
fn wait_wake() {
3153
let t = Instant::now();
@@ -43,3 +65,21 @@ fn wait_wake() {
4365
assert!((90..400).contains(&t.elapsed().as_millis()));
4466
});
4567
}
68+
69+
#[test]
70+
fn wait_wake_u64() {
71+
let t = Instant::now();
72+
let a = AtomicU64::new(0);
73+
std::thread::scope(|s| {
74+
s.spawn(|| {
75+
sleep(Duration::from_millis(100));
76+
a.store(1, Relaxed);
77+
wake_one_u64(&a);
78+
});
79+
while a.load(Relaxed) == 0 {
80+
wait_u64(&a, 0);
81+
}
82+
assert_eq!(a.load(Relaxed), 1);
83+
assert!((90..400).contains(&t.elapsed().as_millis()));
84+
});
85+
}

0 commit comments

Comments
 (0)