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