1 | // Copyright 2018 Amanieu d'Antras |
2 | // |
3 | // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or |
4 | // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or |
5 | // http://opensource.org/licenses/MIT>, at your option. This file may not be |
6 | // copied, modified, or distributed except according to those terms. |
7 | |
8 | use core::cell::UnsafeCell; |
9 | use core::fmt; |
10 | use core::marker::PhantomData; |
11 | use core::mem; |
12 | use core::ops::{Deref, DerefMut}; |
13 | |
14 | #[cfg (feature = "arc_lock" )] |
15 | use alloc::sync::Arc; |
16 | #[cfg (feature = "arc_lock" )] |
17 | use core::mem::ManuallyDrop; |
18 | #[cfg (feature = "arc_lock" )] |
19 | use core::ptr; |
20 | |
21 | #[cfg (feature = "owning_ref" )] |
22 | use owning_ref::StableAddress; |
23 | |
24 | #[cfg (feature = "serde" )] |
25 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; |
26 | |
27 | /// Basic operations for a mutex. |
28 | /// |
29 | /// Types implementing this trait can be used by `Mutex` to form a safe and |
30 | /// fully-functioning mutex type. |
31 | /// |
32 | /// # Safety |
33 | /// |
34 | /// Implementations of this trait must ensure that the mutex is actually |
35 | /// exclusive: a lock can't be acquired while the mutex is already locked. |
36 | pub unsafe trait RawMutex { |
37 | /// Initial value for an unlocked mutex. |
38 | // A “non-constant” const item is a legacy way to supply an initialized value to downstream |
39 | // static items. Can hopefully be replaced with `const fn new() -> Self` at some point. |
40 | #[allow (clippy::declare_interior_mutable_const)] |
41 | const INIT: Self; |
42 | |
43 | /// Marker type which determines whether a lock guard should be `Send`. Use |
44 | /// one of the `GuardSend` or `GuardNoSend` helper types here. |
45 | type GuardMarker; |
46 | |
47 | /// Acquires this mutex, blocking the current thread until it is able to do so. |
48 | fn lock(&self); |
49 | |
50 | /// Attempts to acquire this mutex without blocking. Returns `true` |
51 | /// if the lock was successfully acquired and `false` otherwise. |
52 | fn try_lock(&self) -> bool; |
53 | |
54 | /// Unlocks this mutex. |
55 | /// |
56 | /// # Safety |
57 | /// |
58 | /// This method may only be called if the mutex is held in the current context, i.e. it must |
59 | /// be paired with a successful call to [`lock`], [`try_lock`], [`try_lock_for`] or [`try_lock_until`]. |
60 | /// |
61 | /// [`lock`]: #tymethod.lock |
62 | /// [`try_lock`]: #tymethod.try_lock |
63 | /// [`try_lock_for`]: trait.RawMutexTimed.html#tymethod.try_lock_for |
64 | /// [`try_lock_until`]: trait.RawMutexTimed.html#tymethod.try_lock_until |
65 | unsafe fn unlock(&self); |
66 | |
67 | /// Checks whether the mutex is currently locked. |
68 | #[inline ] |
69 | fn is_locked(&self) -> bool { |
70 | let acquired_lock = self.try_lock(); |
71 | if acquired_lock { |
72 | // Safety: The lock has been successfully acquired above. |
73 | unsafe { |
74 | self.unlock(); |
75 | } |
76 | } |
77 | !acquired_lock |
78 | } |
79 | } |
80 | |
81 | /// Additional methods for mutexes which support fair unlocking. |
82 | /// |
83 | /// Fair unlocking means that a lock is handed directly over to the next waiting |
84 | /// thread if there is one, without giving other threads the opportunity to |
85 | /// "steal" the lock in the meantime. This is typically slower than unfair |
86 | /// unlocking, but may be necessary in certain circumstances. |
87 | pub unsafe trait RawMutexFair: RawMutex { |
88 | /// Unlocks this mutex using a fair unlock protocol. |
89 | /// |
90 | /// # Safety |
91 | /// |
92 | /// This method may only be called if the mutex is held in the current context, see |
93 | /// the documentation of [`unlock`]. |
94 | /// |
95 | /// [`unlock`]: trait.RawMutex.html#tymethod.unlock |
96 | unsafe fn unlock_fair(&self); |
97 | |
98 | /// Temporarily yields the mutex to a waiting thread if there is one. |
99 | /// |
100 | /// This method is functionally equivalent to calling `unlock_fair` followed |
101 | /// by `lock`, however it can be much more efficient in the case where there |
102 | /// are no waiting threads. |
103 | /// |
104 | /// # Safety |
105 | /// |
106 | /// This method may only be called if the mutex is held in the current context, see |
107 | /// the documentation of [`unlock`]. |
108 | /// |
109 | /// [`unlock`]: trait.RawMutex.html#tymethod.unlock |
110 | unsafe fn bump(&self) { |
111 | self.unlock_fair(); |
112 | self.lock(); |
113 | } |
114 | } |
115 | |
116 | /// Additional methods for mutexes which support locking with timeouts. |
117 | /// |
118 | /// The `Duration` and `Instant` types are specified as associated types so that |
119 | /// this trait is usable even in `no_std` environments. |
120 | pub unsafe trait RawMutexTimed: RawMutex { |
121 | /// Duration type used for `try_lock_for`. |
122 | type Duration; |
123 | |
124 | /// Instant type used for `try_lock_until`. |
125 | type Instant; |
126 | |
127 | /// Attempts to acquire this lock until a timeout is reached. |
128 | fn try_lock_for(&self, timeout: Self::Duration) -> bool; |
129 | |
130 | /// Attempts to acquire this lock until a timeout is reached. |
131 | fn try_lock_until(&self, timeout: Self::Instant) -> bool; |
132 | } |
133 | |
134 | /// A mutual exclusion primitive useful for protecting shared data |
135 | /// |
136 | /// This mutex will block threads waiting for the lock to become available. The |
137 | /// mutex can also be statically initialized or created via a `new` |
138 | /// constructor. Each mutex has a type parameter which represents the data that |
139 | /// it is protecting. The data can only be accessed through the RAII guards |
140 | /// returned from `lock` and `try_lock`, which guarantees that the data is only |
141 | /// ever accessed when the mutex is locked. |
142 | pub struct Mutex<R, T: ?Sized> { |
143 | raw: R, |
144 | data: UnsafeCell<T>, |
145 | } |
146 | |
147 | unsafe impl<R: RawMutex + Send, T: ?Sized + Send> Send for Mutex<R, T> {} |
148 | unsafe impl<R: RawMutex + Sync, T: ?Sized + Send> Sync for Mutex<R, T> {} |
149 | |
150 | impl<R: RawMutex, T> Mutex<R, T> { |
151 | /// Creates a new mutex in an unlocked state ready for use. |
152 | #[cfg (has_const_fn_trait_bound)] |
153 | #[inline ] |
154 | pub const fn new(val: T) -> Mutex<R, T> { |
155 | Mutex { |
156 | raw: R::INIT, |
157 | data: UnsafeCell::new(val), |
158 | } |
159 | } |
160 | |
161 | /// Creates a new mutex in an unlocked state ready for use. |
162 | #[cfg (not(has_const_fn_trait_bound))] |
163 | #[inline ] |
164 | pub fn new(val: T) -> Mutex<R, T> { |
165 | Mutex { |
166 | raw: R::INIT, |
167 | data: UnsafeCell::new(val), |
168 | } |
169 | } |
170 | |
171 | /// Consumes this mutex, returning the underlying data. |
172 | #[inline ] |
173 | pub fn into_inner(self) -> T { |
174 | self.data.into_inner() |
175 | } |
176 | } |
177 | |
178 | impl<R, T> Mutex<R, T> { |
179 | /// Creates a new mutex based on a pre-existing raw mutex. |
180 | /// |
181 | /// This allows creating a mutex in a constant context on stable Rust. |
182 | #[inline ] |
183 | pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> { |
184 | Mutex { |
185 | raw: raw_mutex, |
186 | data: UnsafeCell::new(val), |
187 | } |
188 | } |
189 | } |
190 | |
191 | impl<R: RawMutex, T: ?Sized> Mutex<R, T> { |
192 | /// # Safety |
193 | /// |
194 | /// The lock must be held when calling this method. |
195 | #[inline ] |
196 | unsafe fn guard(&self) -> MutexGuard<'_, R, T> { |
197 | MutexGuard { |
198 | mutex: self, |
199 | marker: PhantomData, |
200 | } |
201 | } |
202 | |
203 | /// Acquires a mutex, blocking the current thread until it is able to do so. |
204 | /// |
205 | /// This function will block the local thread until it is available to acquire |
206 | /// the mutex. Upon returning, the thread is the only thread with the mutex |
207 | /// held. An RAII guard is returned to allow scoped unlock of the lock. When |
208 | /// the guard goes out of scope, the mutex will be unlocked. |
209 | /// |
210 | /// Attempts to lock a mutex in the thread which already holds the lock will |
211 | /// result in a deadlock. |
212 | #[inline ] |
213 | pub fn lock(&self) -> MutexGuard<'_, R, T> { |
214 | self.raw.lock(); |
215 | // SAFETY: The lock is held, as required. |
216 | unsafe { self.guard() } |
217 | } |
218 | |
219 | /// Attempts to acquire this lock. |
220 | /// |
221 | /// If the lock could not be acquired at this time, then `None` is returned. |
222 | /// Otherwise, an RAII guard is returned. The lock will be unlocked when the |
223 | /// guard is dropped. |
224 | /// |
225 | /// This function does not block. |
226 | #[inline ] |
227 | pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> { |
228 | if self.raw.try_lock() { |
229 | // SAFETY: The lock is held, as required. |
230 | Some(unsafe { self.guard() }) |
231 | } else { |
232 | None |
233 | } |
234 | } |
235 | |
236 | /// Returns a mutable reference to the underlying data. |
237 | /// |
238 | /// Since this call borrows the `Mutex` mutably, no actual locking needs to |
239 | /// take place---the mutable borrow statically guarantees no locks exist. |
240 | #[inline ] |
241 | pub fn get_mut(&mut self) -> &mut T { |
242 | unsafe { &mut *self.data.get() } |
243 | } |
244 | |
245 | /// Checks whether the mutex is currently locked. |
246 | #[inline ] |
247 | pub fn is_locked(&self) -> bool { |
248 | self.raw.is_locked() |
249 | } |
250 | |
251 | /// Forcibly unlocks the mutex. |
252 | /// |
253 | /// This is useful when combined with `mem::forget` to hold a lock without |
254 | /// the need to maintain a `MutexGuard` object alive, for example when |
255 | /// dealing with FFI. |
256 | /// |
257 | /// # Safety |
258 | /// |
259 | /// This method must only be called if the current thread logically owns a |
260 | /// `MutexGuard` but that guard has been discarded using `mem::forget`. |
261 | /// Behavior is undefined if a mutex is unlocked when not locked. |
262 | #[inline ] |
263 | pub unsafe fn force_unlock(&self) { |
264 | self.raw.unlock(); |
265 | } |
266 | |
267 | /// Returns the underlying raw mutex object. |
268 | /// |
269 | /// Note that you will most likely need to import the `RawMutex` trait from |
270 | /// `lock_api` to be able to call functions on the raw mutex. |
271 | /// |
272 | /// # Safety |
273 | /// |
274 | /// This method is unsafe because it allows unlocking a mutex while |
275 | /// still holding a reference to a `MutexGuard`. |
276 | #[inline ] |
277 | pub unsafe fn raw(&self) -> &R { |
278 | &self.raw |
279 | } |
280 | |
281 | /// Returns a raw pointer to the underlying data. |
282 | /// |
283 | /// This is useful when combined with `mem::forget` to hold a lock without |
284 | /// the need to maintain a `MutexGuard` object alive, for example when |
285 | /// dealing with FFI. |
286 | /// |
287 | /// # Safety |
288 | /// |
289 | /// You must ensure that there are no data races when dereferencing the |
290 | /// returned pointer, for example if the current thread logically owns |
291 | /// a `MutexGuard` but that guard has been discarded using `mem::forget`. |
292 | #[inline ] |
293 | pub fn data_ptr(&self) -> *mut T { |
294 | self.data.get() |
295 | } |
296 | |
297 | /// # Safety |
298 | /// |
299 | /// The lock needs to be held for the behavior of this function to be defined. |
300 | #[cfg (feature = "arc_lock" )] |
301 | #[inline ] |
302 | unsafe fn guard_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> { |
303 | ArcMutexGuard { |
304 | mutex: self.clone(), |
305 | marker: PhantomData, |
306 | } |
307 | } |
308 | |
309 | /// Acquires a lock through an `Arc`. |
310 | /// |
311 | /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc` |
312 | /// and the resulting mutex guard has no lifetime requirements. |
313 | #[cfg (feature = "arc_lock" )] |
314 | #[inline ] |
315 | pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> { |
316 | self.raw.lock(); |
317 | // SAFETY: the locking guarantee is upheld |
318 | unsafe { self.guard_arc() } |
319 | } |
320 | |
321 | /// Attempts to acquire a lock through an `Arc`. |
322 | /// |
323 | /// This method is similar to the `try_lock` method; however, it requires the `Mutex` to be inside of an |
324 | /// `Arc` and the resulting mutex guard has no lifetime requirements. |
325 | #[cfg (feature = "arc_lock" )] |
326 | #[inline ] |
327 | pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> { |
328 | if self.raw.try_lock() { |
329 | // SAFETY: locking guarantee is upheld |
330 | Some(unsafe { self.guard_arc() }) |
331 | } else { |
332 | None |
333 | } |
334 | } |
335 | } |
336 | |
337 | impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> { |
338 | /// Forcibly unlocks the mutex using a fair unlock procotol. |
339 | /// |
340 | /// This is useful when combined with `mem::forget` to hold a lock without |
341 | /// the need to maintain a `MutexGuard` object alive, for example when |
342 | /// dealing with FFI. |
343 | /// |
344 | /// # Safety |
345 | /// |
346 | /// This method must only be called if the current thread logically owns a |
347 | /// `MutexGuard` but that guard has been discarded using `mem::forget`. |
348 | /// Behavior is undefined if a mutex is unlocked when not locked. |
349 | #[inline ] |
350 | pub unsafe fn force_unlock_fair(&self) { |
351 | self.raw.unlock_fair(); |
352 | } |
353 | } |
354 | |
355 | impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> { |
356 | /// Attempts to acquire this lock until a timeout is reached. |
357 | /// |
358 | /// If the lock could not be acquired before the timeout expired, then |
359 | /// `None` is returned. Otherwise, an RAII guard is returned. The lock will |
360 | /// be unlocked when the guard is dropped. |
361 | #[inline ] |
362 | pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> { |
363 | if self.raw.try_lock_for(timeout) { |
364 | // SAFETY: The lock is held, as required. |
365 | Some(unsafe { self.guard() }) |
366 | } else { |
367 | None |
368 | } |
369 | } |
370 | |
371 | /// Attempts to acquire this lock until a timeout is reached. |
372 | /// |
373 | /// If the lock could not be acquired before the timeout expired, then |
374 | /// `None` is returned. Otherwise, an RAII guard is returned. The lock will |
375 | /// be unlocked when the guard is dropped. |
376 | #[inline ] |
377 | pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> { |
378 | if self.raw.try_lock_until(timeout) { |
379 | // SAFETY: The lock is held, as required. |
380 | Some(unsafe { self.guard() }) |
381 | } else { |
382 | None |
383 | } |
384 | } |
385 | |
386 | /// Attempts to acquire this lock through an `Arc` until a timeout is reached. |
387 | /// |
388 | /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an |
389 | /// `Arc` and the resulting mutex guard has no lifetime requirements. |
390 | #[cfg (feature = "arc_lock" )] |
391 | #[inline ] |
392 | pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> { |
393 | if self.raw.try_lock_for(timeout) { |
394 | // SAFETY: locking guarantee is upheld |
395 | Some(unsafe { self.guard_arc() }) |
396 | } else { |
397 | None |
398 | } |
399 | } |
400 | |
401 | /// Attempts to acquire this lock through an `Arc` until a timeout is reached. |
402 | /// |
403 | /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of |
404 | /// an `Arc` and the resulting mutex guard has no lifetime requirements. |
405 | #[cfg (feature = "arc_lock" )] |
406 | #[inline ] |
407 | pub fn try_lock_arc_until( |
408 | self: &Arc<Self>, |
409 | timeout: R::Instant, |
410 | ) -> Option<ArcMutexGuard<R, T>> { |
411 | if self.raw.try_lock_until(timeout) { |
412 | // SAFETY: locking guarantee is upheld |
413 | Some(unsafe { self.guard_arc() }) |
414 | } else { |
415 | None |
416 | } |
417 | } |
418 | } |
419 | |
420 | impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> { |
421 | #[inline ] |
422 | fn default() -> Mutex<R, T> { |
423 | Mutex::new(val:Default::default()) |
424 | } |
425 | } |
426 | |
427 | impl<R: RawMutex, T> From<T> for Mutex<R, T> { |
428 | #[inline ] |
429 | fn from(t: T) -> Mutex<R, T> { |
430 | Mutex::new(val:t) |
431 | } |
432 | } |
433 | |
434 | impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> { |
435 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
436 | match self.try_lock() { |
437 | Some(guard: MutexGuard<'_, R, T>) => f.debug_struct("Mutex" ).field(name:"data" , &&*guard).finish(), |
438 | None => { |
439 | struct LockedPlaceholder; |
440 | impl fmt::Debug for LockedPlaceholder { |
441 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
442 | f.write_str(data:"<locked>" ) |
443 | } |
444 | } |
445 | |
446 | f&mut DebugStruct<'_, '_>.debug_struct("Mutex" ) |
447 | .field(name:"data" , &LockedPlaceholder) |
448 | .finish() |
449 | } |
450 | } |
451 | } |
452 | } |
453 | |
454 | // Copied and modified from serde |
455 | #[cfg (feature = "serde" )] |
456 | impl<R, T> Serialize for Mutex<R, T> |
457 | where |
458 | R: RawMutex, |
459 | T: Serialize + ?Sized, |
460 | { |
461 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
462 | where |
463 | S: Serializer, |
464 | { |
465 | self.lock().serialize(serializer) |
466 | } |
467 | } |
468 | |
469 | #[cfg (feature = "serde" )] |
470 | impl<'de, R, T> Deserialize<'de> for Mutex<R, T> |
471 | where |
472 | R: RawMutex, |
473 | T: Deserialize<'de> + ?Sized, |
474 | { |
475 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
476 | where |
477 | D: Deserializer<'de>, |
478 | { |
479 | Deserialize::deserialize(deserializer).map(Mutex::new) |
480 | } |
481 | } |
482 | |
483 | /// An RAII implementation of a "scoped lock" of a mutex. When this structure is |
484 | /// dropped (falls out of scope), the lock will be unlocked. |
485 | /// |
486 | /// The data protected by the mutex can be accessed through this guard via its |
487 | /// `Deref` and `DerefMut` implementations. |
488 | #[clippy::has_significant_drop] |
489 | #[must_use = "if unused the Mutex will immediately unlock" ] |
490 | pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> { |
491 | mutex: &'a Mutex<R, T>, |
492 | marker: PhantomData<(&'a mut T, R::GuardMarker)>, |
493 | } |
494 | |
495 | unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {} |
496 | |
497 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { |
498 | /// Returns a reference to the original `Mutex` object. |
499 | pub fn mutex(s: &Self) -> &'a Mutex<R, T> { |
500 | s.mutex |
501 | } |
502 | |
503 | /// Makes a new `MappedMutexGuard` for a component of the locked data. |
504 | /// |
505 | /// This operation cannot fail as the `MutexGuard` passed |
506 | /// in already locked the mutex. |
507 | /// |
508 | /// This is an associated function that needs to be |
509 | /// used as `MutexGuard::map(...)`. A method would interfere with methods of |
510 | /// the same name on the contents of the locked data. |
511 | #[inline ] |
512 | pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U> |
513 | where |
514 | F: FnOnce(&mut T) -> &mut U, |
515 | { |
516 | let raw = &s.mutex.raw; |
517 | let data = f(unsafe { &mut *s.mutex.data.get() }); |
518 | mem::forget(s); |
519 | MappedMutexGuard { |
520 | raw, |
521 | data, |
522 | marker: PhantomData, |
523 | } |
524 | } |
525 | |
526 | /// Attempts to make a new `MappedMutexGuard` for a component of the |
527 | /// locked data. The original guard is returned if the closure returns `None`. |
528 | /// |
529 | /// This operation cannot fail as the `MutexGuard` passed |
530 | /// in already locked the mutex. |
531 | /// |
532 | /// This is an associated function that needs to be |
533 | /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of |
534 | /// the same name on the contents of the locked data. |
535 | #[inline ] |
536 | pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self> |
537 | where |
538 | F: FnOnce(&mut T) -> Option<&mut U>, |
539 | { |
540 | let raw = &s.mutex.raw; |
541 | let data = match f(unsafe { &mut *s.mutex.data.get() }) { |
542 | Some(data) => data, |
543 | None => return Err(s), |
544 | }; |
545 | mem::forget(s); |
546 | Ok(MappedMutexGuard { |
547 | raw, |
548 | data, |
549 | marker: PhantomData, |
550 | }) |
551 | } |
552 | |
553 | /// Temporarily unlocks the mutex to execute the given function. |
554 | /// |
555 | /// This is safe because `&mut` guarantees that there exist no other |
556 | /// references to the data protected by the mutex. |
557 | #[inline ] |
558 | pub fn unlocked<F, U>(s: &mut Self, f: F) -> U |
559 | where |
560 | F: FnOnce() -> U, |
561 | { |
562 | // Safety: A MutexGuard always holds the lock. |
563 | unsafe { |
564 | s.mutex.raw.unlock(); |
565 | } |
566 | defer!(s.mutex.raw.lock()); |
567 | f() |
568 | } |
569 | |
570 | /// Leaks the mutex guard and returns a mutable reference to the data |
571 | /// protected by the mutex. |
572 | /// |
573 | /// This will leave the `Mutex` in a locked state. |
574 | #[inline ] |
575 | pub fn leak(s: Self) -> &'a mut T { |
576 | let r = unsafe { &mut *s.mutex.data.get() }; |
577 | mem::forget(s); |
578 | r |
579 | } |
580 | } |
581 | |
582 | impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { |
583 | /// Unlocks the mutex using a fair unlock protocol. |
584 | /// |
585 | /// By default, mutexes are unfair and allow the current thread to re-lock |
586 | /// the mutex before another has the chance to acquire the lock, even if |
587 | /// that thread has been blocked on the mutex for a long time. This is the |
588 | /// default because it allows much higher throughput as it avoids forcing a |
589 | /// context switch on every mutex unlock. This can result in one thread |
590 | /// acquiring a mutex many more times than other threads. |
591 | /// |
592 | /// However in some cases it can be beneficial to ensure fairness by forcing |
593 | /// the lock to pass on to a waiting thread if there is one. This is done by |
594 | /// using this method instead of dropping the `MutexGuard` normally. |
595 | #[inline ] |
596 | pub fn unlock_fair(s: Self) { |
597 | // Safety: A MutexGuard always holds the lock. |
598 | unsafe { |
599 | s.mutex.raw.unlock_fair(); |
600 | } |
601 | mem::forget(s); |
602 | } |
603 | |
604 | /// Temporarily unlocks the mutex to execute the given function. |
605 | /// |
606 | /// The mutex is unlocked using a fair unlock protocol. |
607 | /// |
608 | /// This is safe because `&mut` guarantees that there exist no other |
609 | /// references to the data protected by the mutex. |
610 | #[inline ] |
611 | pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U |
612 | where |
613 | F: FnOnce() -> U, |
614 | { |
615 | // Safety: A MutexGuard always holds the lock. |
616 | unsafe { |
617 | s.mutex.raw.unlock_fair(); |
618 | } |
619 | defer!(s.mutex.raw.lock()); |
620 | f() |
621 | } |
622 | |
623 | /// Temporarily yields the mutex to a waiting thread if there is one. |
624 | /// |
625 | /// This method is functionally equivalent to calling `unlock_fair` followed |
626 | /// by `lock`, however it can be much more efficient in the case where there |
627 | /// are no waiting threads. |
628 | #[inline ] |
629 | pub fn bump(s: &mut Self) { |
630 | // Safety: A MutexGuard always holds the lock. |
631 | unsafe { |
632 | s.mutex.raw.bump(); |
633 | } |
634 | } |
635 | } |
636 | |
637 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> { |
638 | type Target = T; |
639 | #[inline ] |
640 | fn deref(&self) -> &T { |
641 | unsafe { &*self.mutex.data.get() } |
642 | } |
643 | } |
644 | |
645 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> { |
646 | #[inline ] |
647 | fn deref_mut(&mut self) -> &mut T { |
648 | unsafe { &mut *self.mutex.data.get() } |
649 | } |
650 | } |
651 | |
652 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> { |
653 | #[inline ] |
654 | fn drop(&mut self) { |
655 | // Safety: A MutexGuard always holds the lock. |
656 | unsafe { |
657 | self.mutex.raw.unlock(); |
658 | } |
659 | } |
660 | } |
661 | |
662 | impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> { |
663 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
664 | fmt::Debug::fmt(&**self, f) |
665 | } |
666 | } |
667 | |
668 | impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> { |
669 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
670 | (**self).fmt(f) |
671 | } |
672 | } |
673 | |
674 | #[cfg (feature = "owning_ref" )] |
675 | unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {} |
676 | |
677 | /// An RAII mutex guard returned by the `Arc` locking operations on `Mutex`. |
678 | /// |
679 | /// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it |
680 | /// uses an `Arc<Mutex>`. This has several advantages, most notably that it has an `'static` lifetime. |
681 | #[cfg (feature = "arc_lock" )] |
682 | #[clippy::has_significant_drop] |
683 | #[must_use = "if unused the Mutex will immediately unlock" ] |
684 | pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> { |
685 | mutex: Arc<Mutex<R, T>>, |
686 | marker: PhantomData<*const ()>, |
687 | } |
688 | |
689 | #[cfg (feature = "arc_lock" )] |
690 | unsafe impl<R: RawMutex + Send + Sync, T: Send + ?Sized> Send for ArcMutexGuard<R, T> where |
691 | R::GuardMarker: Send |
692 | { |
693 | } |
694 | #[cfg (feature = "arc_lock" )] |
695 | unsafe impl<R: RawMutex + Sync, T: Sync + ?Sized> Sync for ArcMutexGuard<R, T> where |
696 | R::GuardMarker: Sync |
697 | { |
698 | } |
699 | |
700 | #[cfg (feature = "arc_lock" )] |
701 | impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> { |
702 | /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`. |
703 | #[inline ] |
704 | pub fn mutex(s: &Self) -> &Arc<Mutex<R, T>> { |
705 | &s.mutex |
706 | } |
707 | |
708 | /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`]. |
709 | #[inline ] |
710 | pub fn into_arc(s: Self) -> Arc<Mutex<R, T>> { |
711 | // Safety: Skip our Drop impl and manually unlock the mutex. |
712 | let arc = unsafe { ptr::read(&s.mutex) }; |
713 | mem::forget(s); |
714 | unsafe { |
715 | arc.raw.unlock(); |
716 | } |
717 | arc |
718 | } |
719 | |
720 | /// Temporarily unlocks the mutex to execute the given function. |
721 | /// |
722 | /// This is safe because `&mut` guarantees that there exist no other |
723 | /// references to the data protected by the mutex. |
724 | #[inline ] |
725 | pub fn unlocked<F, U>(s: &mut Self, f: F) -> U |
726 | where |
727 | F: FnOnce() -> U, |
728 | { |
729 | // Safety: A MutexGuard always holds the lock. |
730 | unsafe { |
731 | s.mutex.raw.unlock(); |
732 | } |
733 | defer!(s.mutex.raw.lock()); |
734 | f() |
735 | } |
736 | } |
737 | |
738 | #[cfg (feature = "arc_lock" )] |
739 | impl<R: RawMutexFair, T: ?Sized> ArcMutexGuard<R, T> { |
740 | /// Unlocks the mutex using a fair unlock protocol. |
741 | /// |
742 | /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`]. |
743 | #[inline ] |
744 | pub fn unlock_fair(s: Self) { |
745 | // Safety: A MutexGuard always holds the lock. |
746 | unsafe { |
747 | s.mutex.raw.unlock_fair(); |
748 | } |
749 | |
750 | // SAFETY: make sure the Arc gets it reference decremented |
751 | let mut s = ManuallyDrop::new(s); |
752 | unsafe { ptr::drop_in_place(&mut s.mutex) }; |
753 | } |
754 | |
755 | /// Temporarily unlocks the mutex to execute the given function. |
756 | /// |
757 | /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`]. |
758 | #[inline ] |
759 | pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U |
760 | where |
761 | F: FnOnce() -> U, |
762 | { |
763 | // Safety: A MutexGuard always holds the lock. |
764 | unsafe { |
765 | s.mutex.raw.unlock_fair(); |
766 | } |
767 | defer!(s.mutex.raw.lock()); |
768 | f() |
769 | } |
770 | |
771 | /// Temporarily yields the mutex to a waiting thread if there is one. |
772 | /// |
773 | /// This is functionally identical to the `bump` method on [`MutexGuard`]. |
774 | #[inline ] |
775 | pub fn bump(s: &mut Self) { |
776 | // Safety: A MutexGuard always holds the lock. |
777 | unsafe { |
778 | s.mutex.raw.bump(); |
779 | } |
780 | } |
781 | } |
782 | |
783 | #[cfg (feature = "arc_lock" )] |
784 | impl<R: RawMutex, T: ?Sized> Deref for ArcMutexGuard<R, T> { |
785 | type Target = T; |
786 | #[inline ] |
787 | fn deref(&self) -> &T { |
788 | unsafe { &*self.mutex.data.get() } |
789 | } |
790 | } |
791 | |
792 | #[cfg (feature = "arc_lock" )] |
793 | impl<R: RawMutex, T: ?Sized> DerefMut for ArcMutexGuard<R, T> { |
794 | #[inline ] |
795 | fn deref_mut(&mut self) -> &mut T { |
796 | unsafe { &mut *self.mutex.data.get() } |
797 | } |
798 | } |
799 | |
800 | #[cfg (feature = "arc_lock" )] |
801 | impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> { |
802 | #[inline ] |
803 | fn drop(&mut self) { |
804 | // Safety: A MutexGuard always holds the lock. |
805 | unsafe { |
806 | self.mutex.raw.unlock(); |
807 | } |
808 | } |
809 | } |
810 | |
811 | /// An RAII mutex guard returned by `MutexGuard::map`, which can point to a |
812 | /// subfield of the protected data. |
813 | /// |
814 | /// The main difference between `MappedMutexGuard` and `MutexGuard` is that the |
815 | /// former doesn't support temporarily unlocking and re-locking, since that |
816 | /// could introduce soundness issues if the locked object is modified by another |
817 | /// thread. |
818 | #[clippy::has_significant_drop] |
819 | #[must_use = "if unused the Mutex will immediately unlock" ] |
820 | pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> { |
821 | raw: &'a R, |
822 | data: *mut T, |
823 | marker: PhantomData<&'a mut T>, |
824 | } |
825 | |
826 | unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync |
827 | for MappedMutexGuard<'a, R, T> |
828 | { |
829 | } |
830 | unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Send + 'a> Send for MappedMutexGuard<'a, R, T> where |
831 | R::GuardMarker: Send |
832 | { |
833 | } |
834 | |
835 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { |
836 | /// Makes a new `MappedMutexGuard` for a component of the locked data. |
837 | /// |
838 | /// This operation cannot fail as the `MappedMutexGuard` passed |
839 | /// in already locked the mutex. |
840 | /// |
841 | /// This is an associated function that needs to be |
842 | /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of |
843 | /// the same name on the contents of the locked data. |
844 | #[inline ] |
845 | pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U> |
846 | where |
847 | F: FnOnce(&mut T) -> &mut U, |
848 | { |
849 | let raw = s.raw; |
850 | let data = f(unsafe { &mut *s.data }); |
851 | mem::forget(s); |
852 | MappedMutexGuard { |
853 | raw, |
854 | data, |
855 | marker: PhantomData, |
856 | } |
857 | } |
858 | |
859 | /// Attempts to make a new `MappedMutexGuard` for a component of the |
860 | /// locked data. The original guard is returned if the closure returns `None`. |
861 | /// |
862 | /// This operation cannot fail as the `MappedMutexGuard` passed |
863 | /// in already locked the mutex. |
864 | /// |
865 | /// This is an associated function that needs to be |
866 | /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of |
867 | /// the same name on the contents of the locked data. |
868 | #[inline ] |
869 | pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self> |
870 | where |
871 | F: FnOnce(&mut T) -> Option<&mut U>, |
872 | { |
873 | let raw = s.raw; |
874 | let data = match f(unsafe { &mut *s.data }) { |
875 | Some(data) => data, |
876 | None => return Err(s), |
877 | }; |
878 | mem::forget(s); |
879 | Ok(MappedMutexGuard { |
880 | raw, |
881 | data, |
882 | marker: PhantomData, |
883 | }) |
884 | } |
885 | } |
886 | |
887 | impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { |
888 | /// Unlocks the mutex using a fair unlock protocol. |
889 | /// |
890 | /// By default, mutexes are unfair and allow the current thread to re-lock |
891 | /// the mutex before another has the chance to acquire the lock, even if |
892 | /// that thread has been blocked on the mutex for a long time. This is the |
893 | /// default because it allows much higher throughput as it avoids forcing a |
894 | /// context switch on every mutex unlock. This can result in one thread |
895 | /// acquiring a mutex many more times than other threads. |
896 | /// |
897 | /// However in some cases it can be beneficial to ensure fairness by forcing |
898 | /// the lock to pass on to a waiting thread if there is one. This is done by |
899 | /// using this method instead of dropping the `MutexGuard` normally. |
900 | #[inline ] |
901 | pub fn unlock_fair(s: Self) { |
902 | // Safety: A MutexGuard always holds the lock. |
903 | unsafe { |
904 | s.raw.unlock_fair(); |
905 | } |
906 | mem::forget(s); |
907 | } |
908 | } |
909 | |
910 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> { |
911 | type Target = T; |
912 | #[inline ] |
913 | fn deref(&self) -> &T { |
914 | unsafe { &*self.data } |
915 | } |
916 | } |
917 | |
918 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> { |
919 | #[inline ] |
920 | fn deref_mut(&mut self) -> &mut T { |
921 | unsafe { &mut *self.data } |
922 | } |
923 | } |
924 | |
925 | impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> { |
926 | #[inline ] |
927 | fn drop(&mut self) { |
928 | // Safety: A MappedMutexGuard always holds the lock. |
929 | unsafe { |
930 | self.raw.unlock(); |
931 | } |
932 | } |
933 | } |
934 | |
935 | impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> { |
936 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
937 | fmt::Debug::fmt(&**self, f) |
938 | } |
939 | } |
940 | |
941 | impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display |
942 | for MappedMutexGuard<'a, R, T> |
943 | { |
944 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
945 | (**self).fmt(f) |
946 | } |
947 | } |
948 | |
949 | #[cfg (feature = "owning_ref" )] |
950 | unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {} |
951 | |