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