ecmascript_futex/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(
3    all(nightly, target_arch = "wasm32"),
4    feature(stdarch_wasm_atomic_wait)
5)]
6
7use core::time::Duration;
8
9use ecmascript_atomics::Racy;
10
11#[cfg(any(target_os = "linux", target_os = "android"))]
12#[path = "linux.rs"]
13mod platform;
14
15#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
16#[path = "macos.rs"]
17mod platform;
18
19#[cfg(windows)]
20#[path = "windows.rs"]
21mod platform;
22
23#[cfg(target_os = "freebsd")]
24#[path = "freebsd.rs"]
25mod platform;
26
27#[cfg(target_arch = "wasm32")]
28#[path = "wasm32.rs"]
29mod platform;
30
31#[cfg(not(any(
32    target_arch = "wasm32",
33    target_os = "linux",
34    target_os = "android",
35    target_os = "freebsd",
36    target_os = "macos",
37    target_os = "ios",
38    target_os = "watchos",
39    windows
40)))]
41#[path = "fallback.rs"]
42mod platform;
43
44/// A table of OS synchronization primitives for manually
45/// implementing futex functionality on unsupported platforms.
46#[cfg(not(any(
47    target_os = "freebsd",
48    target_os = "macos",
49    target_os = "ios",
50    target_os = "watchos",
51    windows
52)))]
53mod condvar_table;
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum FutexError {
57    /// The value was not equal and no sleep was performed.
58    NotEqual,
59    /// Timeout fired.
60    Timeout,
61    /// An unknown error occurred.
62    Unknown,
63}
64
65/// A type that supports atomic waits.
66pub trait ECMAScriptAtomicWait: private::ECMAScriptAtomicWaitImpl {
67    /// If the value is `value`, wait until woken up.
68    ///
69    /// This function might also return spuriously,
70    /// without a corresponding wake operation.
71    fn wait(&self, value: Self::AtomicInner) -> Result<(), FutexError> {
72        private::ECMAScriptAtomicWaitImpl::wait_timeout(self, value, None)
73    }
74
75    /// If the value is `value`, wait until timeout elapses
76    /// or notify is called.
77    ///
78    /// This function might also return spuriously,
79    /// without a corresponding wake operation.
80    fn wait_timeout(&self, value: Self::AtomicInner, timeout: Duration) -> Result<(), FutexError> {
81        private::ECMAScriptAtomicWaitImpl::wait_timeout(self, value, Some(timeout))
82    }
83
84    /// Wake one thread that is waiting on this atomic.
85    fn notify_many(&self, count: usize) -> usize {
86        private::ECMAScriptAtomicWaitImpl::notify_many(self, count)
87    }
88
89    /// Wake all threads that are waiting on this atomic.
90    fn notify_all(&self) -> usize {
91        private::ECMAScriptAtomicWaitImpl::notify_all(self)
92    }
93}
94
95impl ECMAScriptAtomicWait for Racy<'_, u32> {}
96impl ECMAScriptAtomicWait for Racy<'_, u64> {}
97
98/// Private implementation details.
99mod private {
100    use core::time::Duration;
101
102    use crate::FutexError;
103
104    /// A trait that cannot be implemented by other crates.
105    pub trait ECMAScriptAtomicWaitImpl {
106        /// The underlying integer type for the atomic.
107        type AtomicInner;
108
109        /// Wake all threads that are waiting on this atomic.
110        fn notify_all(&self) -> usize;
111
112        /// Wake one thread that is waiting on this atomic.
113        fn notify_many(&self, count: usize) -> usize;
114
115        /// If the value is `value`, wait until woken up.
116        ///
117        /// This function might also return spuriously,
118        /// without a corresponding wake operation.
119        fn wait_timeout(
120            &self,
121            value: Self::AtomicInner,
122            timeout: Option<Duration>,
123        ) -> Result<(), FutexError>;
124    }
125}