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}