about summary refs log tree commit diff
path: root/library/std/src/sys/pal/windows/futex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/pal/windows/futex.rs')
-rw-r--r--library/std/src/sys/pal/windows/futex.rs52
1 files changed, 52 insertions, 0 deletions
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
new file mode 100644
index 00000000000..88f20ed270b
--- /dev/null
+++ b/library/std/src/sys/pal/windows/futex.rs
@@ -0,0 +1,52 @@
+use super::api;
+use crate::sys::c;
+use crate::sys::dur2timeout;
+use core::ffi::c_void;
+use core::mem;
+use core::ptr;
+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>());
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        let size = mem::size_of::<T>();
+        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>();
+        c::WakeByAddressSingle(addr);
+    }
+}
+
+#[inline(always)]
+pub fn wake_by_address_all<T>(address: &T) {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        c::WakeByAddressAll(addr);
+    }
+}
+
+#[inline(always)]
+pub fn futex_wait<T, U>(futex: &T, expected: U, 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)
+}