nstd_sys/
timed_mutex.rs

1//! A mutual exclusion primitive with a timed locking mechanism.
2use crate::{
3    core::time::NSTDDuration,
4    heap_ptr::{NSTDHeapPtr, NSTDOptionalHeapPtr},
5    NSTDAny, NSTDAnyMut, NSTDBool,
6};
7use cfg_if::cfg_if;
8
9cfg_if! {
10    if #[cfg(any(
11        target_os = "android",
12        target_os = "dragonfly",
13        target_os = "freebsd",
14        target_os = "haiku",
15        target_os = "linux",
16        target_os = "netbsd",
17        target_os = "nto",
18        target_os = "openbsd",
19        target_os = "solaris"
20    ))] {
21        use crate::os::unix::mutex::{
22            NSTDUnixMutex, NSTDUnixMutexGuard, NSTDUnixMutexLockResult, NSTDUnixOptionalMutex,
23            NSTDUnixOptionalMutexLockResult,
24        };
25
26        /// A mutual exclusion primitive with a timed locking mechanism.
27        pub type NSTDTimedMutex<'a> = NSTDUnixMutex<'a>;
28
29        /// Represents an optional value of type `NSTDTimedMutex`.
30        pub type NSTDOptionalTimedMutex<'a> = NSTDUnixOptionalMutex<'a>;
31
32        /// A handle to a timed mutex's data.
33        pub type NSTDTimedMutexGuard<'m, 'a> = NSTDUnixMutexGuard<'m, 'a>;
34
35        /// A result type containing a timed mutex lock whether or not the mutex is poisoned.
36        pub type NSTDTimedMutexLockResult<'m, 'a> = NSTDUnixMutexLockResult<'m, 'a>;
37
38        /// An optional value of type `NSTDTimedMutexLockResult`.
39        ///
40        /// This type is returned from `nstd_timed_mutex_try_lock` where the uninitialized variant
41        /// means that the function would block.
42        pub type NSTDOptionalTimedMutexLockResult<'m, 'a> = NSTDUnixOptionalMutexLockResult<'m, 'a>;
43    } else {
44        use crate::core::{optional::NSTDOptional, result::NSTDResult};
45        use core::{marker::PhantomData, mem::ManuallyDrop};
46        use nstdapi::nstdapi;
47
48        /// A mutual exclusion primitive with a timed locking mechanism.
49        #[nstdapi]
50        pub struct NSTDTimedMutex<'a> {
51            /// The underlying mutex.
52            inner: NSTDAnyMut,
53            /// The data to protect.
54            data: ManuallyDrop<NSTDHeapPtr<'a>>,
55            /// Determines whether or not the mutex is poisoned.
56            poisoned: NSTDBool,
57            /// Determines whether or not the mutex is currently locked.
58            locked: NSTDBool,
59        }
60        impl Drop for NSTDTimedMutex<'_> {
61            /// [`NSTDTimedMutex`]'s destructor.
62            #[inline]
63            fn drop(&mut self) {
64                // SAFETY: `NSTDTimeMutex` has been initialized and is valid for reads.
65                unsafe { nstd_timed_mutex_free(core::ptr::read(self)) };
66            }
67        }
68        /// # Safety
69        ///
70        /// The data that the mutex is protecting must be able to be safely sent between threads.
71        // SAFETY: The user guarantees that the data is thread-safe.
72        unsafe impl Send for NSTDTimedMutex<'_> {}
73        /// # Safety
74        ///
75        /// The data that the mutex is protecting must be able to be safely shared between threads.
76        // SAFETY: The user guarantees that the data is thread-safe.
77        unsafe impl Sync for NSTDTimedMutex<'_> {}
78
79        /// Represents an optional value of type `NSTDTimedMutex`.
80        pub type NSTDOptionalTimedMutex<'a> = NSTDOptional<NSTDTimedMutex<'a>>;
81
82        /// A handle to a timed mutex's data.
83        #[nstdapi]
84        pub struct NSTDTimedMutexGuard<'m, 'a> {
85            /// A reference to the mutex.
86            mutex: &'m NSTDTimedMutex<'a>,
87            /// Ensures that the guard is not [Send].
88            pd: PhantomData<*const ()>,
89        }
90        impl Drop for NSTDTimedMutexGuard<'_, '_> {
91            /// [`NSTDTimedMutexGuard`]'s destructor.
92            #[inline]
93            fn drop(&mut self) {
94                // SAFETY: `self` is a valid guard for the mutex.
95                unsafe { nstd_timed_mutex_unlock(core::ptr::read(self)) };
96            }
97        }
98        /// # Safety
99        ///
100        /// The data that the guard is protecting must be able to be safely shared between threads.
101        // SAFETY: The user guarantees that the data is thread-safe.
102        unsafe impl Sync for NSTDTimedMutexGuard<'_, '_> {}
103
104        /// A result type containing a timed mutex lock whether or not the mutex is poisoned.
105        pub type NSTDTimedMutexLockResult<'m, 'a> =
106            NSTDResult<NSTDTimedMutexGuard<'m, 'a>, NSTDTimedMutexGuard<'m, 'a>>;
107
108        /// An optional value of type `NSTDTimedMutexLockResult`.
109        ///
110        /// This type is returned from `nstd_timed_mutex_try_lock` where the uninitialized variant
111        /// means that the function would block.
112        pub type NSTDOptionalTimedMutexLockResult<'m, 'a> =
113            NSTDOptional<NSTDTimedMutexLockResult<'m, 'a>>;
114    }
115}
116
117extern "C" {
118    /// Creates a new timed mutual exclusion primitive.
119    ///
120    /// # Parameters:
121    ///
122    /// - `NSTDHeapPtr data` - The data to protect.
123    ///
124    /// # Returns
125    ///
126    /// `NSTDOptionalTimedMutex mutex` - The new mutex protecting `data` on success, or an
127    /// uninitialized "none" value if the OS failed to initialize the mutex.
128    pub fn nstd_timed_mutex_new(data: NSTDHeapPtr<'_>) -> NSTDOptionalTimedMutex<'_>;
129
130    /// Determines whether or not a timed mutex's data is poisoned.
131    ///
132    /// Mutexes are poisoned when a thread that owns the mutex guard panics. This function is useful
133    /// for those that configure `nstd` to unwind the stack instead of aborting on panic.
134    ///
135    /// # Parameters:
136    ///
137    /// - `const NSTDTimedMutex *mutex` - The mutex.
138    ///
139    /// # Returns
140    ///
141    /// `NSTDBool is_poisoned` - A boolean value indicating whether or not `mutex` is poisoned.
142    pub fn nstd_timed_mutex_is_poisoned(mutex: &NSTDTimedMutex<'_>) -> NSTDBool;
143
144    /// Waits for a timed mutex lock to become acquired, returning a guard wrapping the protected data.
145    ///
146    /// Attempting to call this function on a thread that already owns the lock will result in
147    /// undefined behavior.
148    ///
149    /// # Parameters:
150    ///
151    /// - `const NSTDTimedMutex *mutex` - The mutex to lock.
152    ///
153    /// # Returns
154    ///
155    /// `NSTDOptionalTimedMutexLockResult guard` - A handle to the mutex's protected data, or an
156    /// uninitialized "none" value if the OS fails to lock the mutex.
157    ///
158    /// # Safety
159    ///
160    /// The mutex lock must not already be owned by the calling thread.
161    pub fn nstd_timed_mutex_lock<'m, 'a>(
162        mutex: &'m NSTDTimedMutex<'a>,
163    ) -> NSTDOptionalTimedMutexLockResult<'m, 'a>;
164
165    /// The non-blocking variant of `nstd_timed_mutex_lock` returning an uninitialized "none" result if
166    /// the mutex is locked by another thread.
167    ///
168    /// Attempting to call this function on a thread that already owns the lock will result in
169    /// undefined behavior.
170    ///
171    /// # Parameters:
172    ///
173    /// - `const NSTDTimedMutex *mutex` - The mutex to lock.
174    ///
175    /// # Returns
176    ///
177    /// `NSTDOptionalTimedMutexLockResult guard` - A handle to the mutex's protected data.
178    ///
179    /// # Safety
180    ///
181    /// The mutex lock must not already be owned by the calling thread.
182    pub fn nstd_timed_mutex_try_lock<'m, 'a>(
183        mutex: &'m NSTDTimedMutex<'a>,
184    ) -> NSTDOptionalTimedMutexLockResult<'m, 'a>;
185
186    /// The timed variant of `nstd_timed_mutex_lock` returning an uninitialized "none" result if
187    /// the mutex lock could not be acquired after a specified number of `seconds`.
188    ///
189    /// Attempting to call this function on a thread that already owns the lock will result in
190    /// undefined behavior.
191    ///
192    /// # Parameters:
193    ///
194    /// - `const NSTDTimedMutex *mutex` - The mutex to lock.
195    ///
196    /// - `NSTDDuration duration` - The amount of time to block for.
197    ///
198    /// # Returns
199    ///
200    /// `NSTDOptionalTimedMutexLockResult guard` - A handle to the mutex's protected data.
201    ///
202    /// # Safety
203    ///
204    /// The mutex lock must not already be owned by the calling thread.
205    pub fn nstd_timed_mutex_timed_lock<'m, 'a>(
206        mutex: &'m NSTDTimedMutex<'a>,
207        duration: NSTDDuration,
208    ) -> NSTDOptionalTimedMutexLockResult<'m, 'a>;
209
210    /// Returns an immutable raw pointer to a timed mutex guard's protected data.
211    ///
212    /// # Parameters:
213    ///
214    /// - `const NSTDTimedMutexGuard *guard` - The mutex guard.
215    ///
216    /// # Returns
217    ///
218    /// `NSTDAny data` - A pointer to the guard's protected data.
219    pub fn nstd_timed_mutex_get(guard: &NSTDTimedMutexGuard<'_, '_>) -> NSTDAny;
220
221    /// Returns an raw pointer to a timed mutex guard's protected data.
222    ///
223    /// # Parameters:
224    ///
225    /// - `NSTDTimedMutexGuard *guard` - The mutex guard.
226    ///
227    /// # Returns
228    ///
229    /// `NSTDAnyMut data` - A pointer to the guard's protected data.
230    pub fn nstd_timed_mutex_get_mut(guard: &mut NSTDTimedMutexGuard<'_, '_>) -> NSTDAnyMut;
231
232    /// Consumes a timed mutex and returns the data it was protecting.
233    ///
234    /// # Parameters:
235    ///
236    /// - `NSTDTimedMutex mutex` - The mutex to take ownership of.
237    ///
238    /// # Returns
239    ///
240    /// `NSTDOptionalHeapPtr data` - Ownership of the mutex's data, or an uninitialized "none"
241    /// variant if the mutex was poisoned.
242    pub fn nstd_timed_mutex_into_inner(mutex: NSTDTimedMutex<'_>) -> NSTDOptionalHeapPtr<'_>;
243
244    /// Unlocks a timed mutex by consuming a mutex guard.
245    ///
246    /// # Parameters:
247    ///
248    /// - `NSTDTimedMutexGuard guard` - The mutex guard.
249    pub fn nstd_timed_mutex_unlock(guard: NSTDTimedMutexGuard<'_, '_>);
250
251    /// Frees an instance of `NSTDTimedMutex`.
252    ///
253    /// # Parameters:
254    ///
255    /// - `NSTDTimedMutex mutex` - The timed mutex to free.
256    pub fn nstd_timed_mutex_free(mutex: NSTDTimedMutex<'_>);
257
258    /// Frees an instance of `NSTDTimedMutex` after invoking `callback` with the mutex's data.
259    ///
260    /// `callback` will not be called if the mutex is poisoned.
261    ///
262    /// # Parameters:
263    ///
264    /// - `NSTDTimedMutex mutex` - The timed mutex to free.
265    ///
266    /// - `void (*callback)(NSTDAnyMut)` - The mutex data's destructor.
267    ///
268    /// # Safety
269    ///
270    /// This operation makes a direct call on a C function pointer (`callback`).
271    pub fn nstd_timed_mutex_drop(
272        mutex: NSTDTimedMutex<'_>,
273        callback: unsafe extern "C" fn(NSTDAnyMut),
274    );
275}