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 = "owning_ref")] 15 use owning_ref::StableAddress; 16 17 #[cfg(feature = "serde")] 18 use serde::{Deserialize, Deserializer, Serialize, Serializer}; 19 20 /// Basic operations for a mutex. 21 /// 22 /// Types implementing this trait can be used by `Mutex` to form a safe and 23 /// fully-functioning mutex type. 24 /// 25 /// # Safety 26 /// 27 /// Implementations of this trait must ensure that the mutex is actually 28 /// exclusive: a lock can't be acquired while the mutex is already locked. 29 pub unsafe trait RawMutex { 30 /// Initial value for an unlocked mutex. 31 // A “non-constant” const item is a legacy way to supply an initialized value to downstream 32 // static items. Can hopefully be replaced with `const fn new() -> Self` at some point. 33 #[allow(clippy::declare_interior_mutable_const)] 34 const INIT: Self; 35 36 /// Marker type which determines whether a lock guard should be `Send`. Use 37 /// one of the `GuardSend` or `GuardNoSend` helper types here. 38 type GuardMarker; 39 40 /// Acquires this mutex, blocking the current thread until it is able to do so. lock(&self)41 fn lock(&self); 42 43 /// Attempts to acquire this mutex without blocking. Returns `true` 44 /// if the lock was successfully acquired and `false` otherwise. try_lock(&self) -> bool45 fn try_lock(&self) -> bool; 46 47 /// Unlocks this mutex. unlock(&self)48 fn unlock(&self); 49 } 50 51 /// Additional methods for mutexes which support fair unlocking. 52 /// 53 /// Fair unlocking means that a lock is handed directly over to the next waiting 54 /// thread if there is one, without giving other threads the opportunity to 55 /// "steal" the lock in the meantime. This is typically slower than unfair 56 /// unlocking, but may be necessary in certain circumstances. 57 pub unsafe trait RawMutexFair: RawMutex { 58 /// Unlocks this mutex using a fair unlock protocol. unlock_fair(&self)59 fn unlock_fair(&self); 60 61 /// Temporarily yields the mutex to a waiting thread if there is one. 62 /// 63 /// This method is functionally equivalent to calling `unlock_fair` followed 64 /// by `lock`, however it can be much more efficient in the case where there 65 /// are no waiting threads. bump(&self)66 fn bump(&self) { 67 self.unlock_fair(); 68 self.lock(); 69 } 70 } 71 72 /// Additional methods for mutexes which support locking with timeouts. 73 /// 74 /// The `Duration` and `Instant` types are specified as associated types so that 75 /// this trait is usable even in `no_std` environments. 76 pub unsafe trait RawMutexTimed: RawMutex { 77 /// Duration type used for `try_lock_for`. 78 type Duration; 79 80 /// Instant type used for `try_lock_until`. 81 type Instant; 82 83 /// Attempts to acquire this lock until a timeout is reached. try_lock_for(&self, timeout: Self::Duration) -> bool84 fn try_lock_for(&self, timeout: Self::Duration) -> bool; 85 86 /// Attempts to acquire this lock until a timeout is reached. try_lock_until(&self, timeout: Self::Instant) -> bool87 fn try_lock_until(&self, timeout: Self::Instant) -> bool; 88 } 89 90 /// A mutual exclusion primitive useful for protecting shared data 91 /// 92 /// This mutex will block threads waiting for the lock to become available. The 93 /// mutex can also be statically initialized or created via a `new` 94 /// constructor. Each mutex has a type parameter which represents the data that 95 /// it is protecting. The data can only be accessed through the RAII guards 96 /// returned from `lock` and `try_lock`, which guarantees that the data is only 97 /// ever accessed when the mutex is locked. 98 pub struct Mutex<R, T: ?Sized> { 99 raw: R, 100 data: UnsafeCell<T>, 101 } 102 103 unsafe impl<R: RawMutex + Send, T: ?Sized + Send> Send for Mutex<R, T> {} 104 unsafe impl<R: RawMutex + Sync, T: ?Sized + Send> Sync for Mutex<R, T> {} 105 106 impl<R: RawMutex, T> Mutex<R, T> { 107 /// Creates a new mutex in an unlocked state ready for use. 108 #[cfg(feature = "nightly")] 109 #[inline] new(val: T) -> Mutex<R, T>110 pub const fn new(val: T) -> Mutex<R, T> { 111 Mutex { 112 raw: R::INIT, 113 data: UnsafeCell::new(val), 114 } 115 } 116 117 /// Creates a new mutex in an unlocked state ready for use. 118 #[cfg(not(feature = "nightly"))] 119 #[inline] new(val: T) -> Mutex<R, T>120 pub fn new(val: T) -> Mutex<R, T> { 121 Mutex { 122 raw: R::INIT, 123 data: UnsafeCell::new(val), 124 } 125 } 126 127 /// Consumes this mutex, returning the underlying data. 128 #[inline] into_inner(self) -> T129 pub fn into_inner(self) -> T { 130 self.data.into_inner() 131 } 132 } 133 134 impl<R, T> Mutex<R, T> { 135 /// Creates a new mutex based on a pre-existing raw mutex. 136 /// 137 /// This allows creating a mutex in a constant context on stable Rust. 138 #[inline] const_new(raw_mutex: R, val: T) -> Mutex<R, T>139 pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> { 140 Mutex { 141 raw: raw_mutex, 142 data: UnsafeCell::new(val), 143 } 144 } 145 } 146 147 impl<R: RawMutex, T: ?Sized> Mutex<R, T> { 148 /// # Safety 149 /// 150 /// The lock must be held when calling this method. 151 #[inline] guard(&self) -> MutexGuard<'_, R, T>152 unsafe fn guard(&self) -> MutexGuard<'_, R, T> { 153 MutexGuard { 154 mutex: self, 155 marker: PhantomData, 156 } 157 } 158 159 /// Acquires a mutex, blocking the current thread until it is able to do so. 160 /// 161 /// This function will block the local thread until it is available to acquire 162 /// the mutex. Upon returning, the thread is the only thread with the mutex 163 /// held. An RAII guard is returned to allow scoped unlock of the lock. When 164 /// the guard goes out of scope, the mutex will be unlocked. 165 /// 166 /// Attempts to lock a mutex in the thread which already holds the lock will 167 /// result in a deadlock. 168 #[inline] lock(&self) -> MutexGuard<'_, R, T>169 pub fn lock(&self) -> MutexGuard<'_, R, T> { 170 self.raw.lock(); 171 // SAFETY: The lock is held, as required. 172 unsafe { self.guard() } 173 } 174 175 /// Attempts to acquire this lock. 176 /// 177 /// If the lock could not be acquired at this time, then `None` is returned. 178 /// Otherwise, an RAII guard is returned. The lock will be unlocked when the 179 /// guard is dropped. 180 /// 181 /// This function does not block. 182 #[inline] try_lock(&self) -> Option<MutexGuard<'_, R, T>>183 pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> { 184 if self.raw.try_lock() { 185 // SAFETY: The lock is held, as required. 186 Some(unsafe { self.guard() }) 187 } else { 188 None 189 } 190 } 191 192 /// Returns a mutable reference to the underlying data. 193 /// 194 /// Since this call borrows the `Mutex` mutably, no actual locking needs to 195 /// take place---the mutable borrow statically guarantees no locks exist. 196 #[inline] get_mut(&mut self) -> &mut T197 pub fn get_mut(&mut self) -> &mut T { 198 unsafe { &mut *self.data.get() } 199 } 200 201 /// Forcibly unlocks the mutex. 202 /// 203 /// This is useful when combined with `mem::forget` to hold a lock without 204 /// the need to maintain a `MutexGuard` object alive, for example when 205 /// dealing with FFI. 206 /// 207 /// # Safety 208 /// 209 /// This method must only be called if the current thread logically owns a 210 /// `MutexGuard` but that guard has be discarded using `mem::forget`. 211 /// Behavior is undefined if a mutex is unlocked when not locked. 212 #[inline] force_unlock(&self)213 pub unsafe fn force_unlock(&self) { 214 self.raw.unlock(); 215 } 216 217 /// Returns the underlying raw mutex object. 218 /// 219 /// Note that you will most likely need to import the `RawMutex` trait from 220 /// `lock_api` to be able to call functions on the raw mutex. 221 /// 222 /// # Safety 223 /// 224 /// This method is unsafe because it allows unlocking a mutex while 225 /// still holding a reference to a `MutexGuard`. 226 #[inline] raw(&self) -> &R227 pub unsafe fn raw(&self) -> &R { 228 &self.raw 229 } 230 } 231 232 impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> { 233 /// Forcibly unlocks the mutex using a fair unlock procotol. 234 /// 235 /// This is useful when combined with `mem::forget` to hold a lock without 236 /// the need to maintain a `MutexGuard` object alive, for example when 237 /// dealing with FFI. 238 /// 239 /// # Safety 240 /// 241 /// This method must only be called if the current thread logically owns a 242 /// `MutexGuard` but that guard has be discarded using `mem::forget`. 243 /// Behavior is undefined if a mutex is unlocked when not locked. 244 #[inline] force_unlock_fair(&self)245 pub unsafe fn force_unlock_fair(&self) { 246 self.raw.unlock_fair(); 247 } 248 } 249 250 impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> { 251 /// Attempts to acquire this lock until a timeout is reached. 252 /// 253 /// If the lock could not be acquired before the timeout expired, then 254 /// `None` is returned. Otherwise, an RAII guard is returned. The lock will 255 /// be unlocked when the guard is dropped. 256 #[inline] try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>>257 pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> { 258 if self.raw.try_lock_for(timeout) { 259 // SAFETY: The lock is held, as required. 260 Some(unsafe { self.guard() }) 261 } else { 262 None 263 } 264 } 265 266 /// Attempts to acquire this lock until a timeout is reached. 267 /// 268 /// If the lock could not be acquired before the timeout expired, then 269 /// `None` is returned. Otherwise, an RAII guard is returned. The lock will 270 /// be unlocked when the guard is dropped. 271 #[inline] try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>>272 pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> { 273 if self.raw.try_lock_until(timeout) { 274 // SAFETY: The lock is held, as required. 275 Some(unsafe { self.guard() }) 276 } else { 277 None 278 } 279 } 280 } 281 282 impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> { 283 #[inline] default() -> Mutex<R, T>284 fn default() -> Mutex<R, T> { 285 Mutex::new(Default::default()) 286 } 287 } 288 289 impl<R: RawMutex, T> From<T> for Mutex<R, T> { 290 #[inline] from(t: T) -> Mutex<R, T>291 fn from(t: T) -> Mutex<R, T> { 292 Mutex::new(t) 293 } 294 } 295 296 impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 298 match self.try_lock() { 299 Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), 300 None => { 301 struct LockedPlaceholder; 302 impl fmt::Debug for LockedPlaceholder { 303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 304 f.write_str("<locked>") 305 } 306 } 307 308 f.debug_struct("Mutex") 309 .field("data", &LockedPlaceholder) 310 .finish() 311 } 312 } 313 } 314 } 315 316 // Copied and modified from serde 317 #[cfg(feature = "serde")] 318 impl<R, T> Serialize for Mutex<R, T> 319 where 320 R: RawMutex, 321 T: Serialize + ?Sized, 322 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,323 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 324 where 325 S: Serializer, 326 { 327 self.lock().serialize(serializer) 328 } 329 } 330 331 #[cfg(feature = "serde")] 332 impl<'de, R, T> Deserialize<'de> for Mutex<R, T> 333 where 334 R: RawMutex, 335 T: Deserialize<'de> + ?Sized, 336 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,337 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 338 where 339 D: Deserializer<'de>, 340 { 341 Deserialize::deserialize(deserializer).map(Mutex::new) 342 } 343 } 344 345 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is 346 /// dropped (falls out of scope), the lock will be unlocked. 347 /// 348 /// The data protected by the mutex can be accessed through this guard via its 349 /// `Deref` and `DerefMut` implementations. 350 #[must_use = "if unused the Mutex will immediately unlock"] 351 pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> { 352 mutex: &'a Mutex<R, T>, 353 marker: PhantomData<(&'a mut T, R::GuardMarker)>, 354 } 355 356 unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {} 357 358 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { 359 /// Returns a reference to the original `Mutex` object. mutex(s: &Self) -> &'a Mutex<R, T>360 pub fn mutex(s: &Self) -> &'a Mutex<R, T> { 361 s.mutex 362 } 363 364 /// Makes a new `MappedMutexGuard` for a component of the locked data. 365 /// 366 /// This operation cannot fail as the `MutexGuard` passed 367 /// in already locked the mutex. 368 /// 369 /// This is an associated function that needs to be 370 /// used as `MutexGuard::map(...)`. A method would interfere with methods of 371 /// the same name on the contents of the locked data. 372 #[inline] map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U> where F: FnOnce(&mut T) -> &mut U,373 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U> 374 where 375 F: FnOnce(&mut T) -> &mut U, 376 { 377 let raw = &s.mutex.raw; 378 let data = f(unsafe { &mut *s.mutex.data.get() }); 379 mem::forget(s); 380 MappedMutexGuard { 381 raw, 382 data, 383 marker: PhantomData, 384 } 385 } 386 387 /// Attempts to make a new `MappedMutexGuard` for a component of the 388 /// locked data. The original guard is returned if the closure returns `None`. 389 /// 390 /// This operation cannot fail as the `MutexGuard` passed 391 /// in already locked the mutex. 392 /// 393 /// This is an associated function that needs to be 394 /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of 395 /// the same name on the contents of the locked data. 396 #[inline] try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>,397 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self> 398 where 399 F: FnOnce(&mut T) -> Option<&mut U>, 400 { 401 let raw = &s.mutex.raw; 402 let data = match f(unsafe { &mut *s.mutex.data.get() }) { 403 Some(data) => data, 404 None => return Err(s), 405 }; 406 mem::forget(s); 407 Ok(MappedMutexGuard { 408 raw, 409 data, 410 marker: PhantomData, 411 }) 412 } 413 414 /// Temporarily unlocks the mutex to execute the given function. 415 /// 416 /// This is safe because `&mut` guarantees that there exist no other 417 /// references to the data protected by the mutex. 418 #[inline] unlocked<F, U>(s: &mut Self, f: F) -> U where F: FnOnce() -> U,419 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U 420 where 421 F: FnOnce() -> U, 422 { 423 s.mutex.raw.unlock(); 424 defer!(s.mutex.raw.lock()); 425 f() 426 } 427 } 428 429 impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { 430 /// Unlocks the mutex using a fair unlock protocol. 431 /// 432 /// By default, mutexes are unfair and allow the current thread to re-lock 433 /// the mutex before another has the chance to acquire the lock, even if 434 /// that thread has been blocked on the mutex for a long time. This is the 435 /// default because it allows much higher throughput as it avoids forcing a 436 /// context switch on every mutex unlock. This can result in one thread 437 /// acquiring a mutex many more times than other threads. 438 /// 439 /// However in some cases it can be beneficial to ensure fairness by forcing 440 /// the lock to pass on to a waiting thread if there is one. This is done by 441 /// using this method instead of dropping the `MutexGuard` normally. 442 #[inline] unlock_fair(s: Self)443 pub fn unlock_fair(s: Self) { 444 s.mutex.raw.unlock_fair(); 445 mem::forget(s); 446 } 447 448 /// Temporarily unlocks the mutex to execute the given function. 449 /// 450 /// The mutex is unlocked using a fair unlock protocol. 451 /// 452 /// This is safe because `&mut` guarantees that there exist no other 453 /// references to the data protected by the mutex. 454 #[inline] unlocked_fair<F, U>(s: &mut Self, f: F) -> U where F: FnOnce() -> U,455 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U 456 where 457 F: FnOnce() -> U, 458 { 459 s.mutex.raw.unlock_fair(); 460 defer!(s.mutex.raw.lock()); 461 f() 462 } 463 464 /// Temporarily yields the mutex to a waiting thread if there is one. 465 /// 466 /// This method is functionally equivalent to calling `unlock_fair` followed 467 /// by `lock`, however it can be much more efficient in the case where there 468 /// are no waiting threads. 469 #[inline] bump(s: &mut Self)470 pub fn bump(s: &mut Self) { 471 s.mutex.raw.bump(); 472 } 473 } 474 475 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> { 476 type Target = T; 477 #[inline] deref(&self) -> &T478 fn deref(&self) -> &T { 479 unsafe { &*self.mutex.data.get() } 480 } 481 } 482 483 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> { 484 #[inline] deref_mut(&mut self) -> &mut T485 fn deref_mut(&mut self) -> &mut T { 486 unsafe { &mut *self.mutex.data.get() } 487 } 488 } 489 490 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> { 491 #[inline] drop(&mut self)492 fn drop(&mut self) { 493 self.mutex.raw.unlock(); 494 } 495 } 496 497 impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result498 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 499 fmt::Debug::fmt(&**self, f) 500 } 501 } 502 503 impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result504 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 505 (**self).fmt(f) 506 } 507 } 508 509 #[cfg(feature = "owning_ref")] 510 unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {} 511 512 /// An RAII mutex guard returned by `MutexGuard::map`, which can point to a 513 /// subfield of the protected data. 514 /// 515 /// The main difference between `MappedMutexGuard` and `MutexGuard` is that the 516 /// former doesn't support temporarily unlocking and re-locking, since that 517 /// could introduce soundness issues if the locked object is modified by another 518 /// thread. 519 #[must_use = "if unused the Mutex will immediately unlock"] 520 pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> { 521 raw: &'a R, 522 data: *mut T, 523 marker: PhantomData<&'a mut T>, 524 } 525 526 unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync 527 for MappedMutexGuard<'a, R, T> 528 { 529 } 530 unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Send for MappedMutexGuard<'a, R, T> where 531 R::GuardMarker: Send 532 { 533 } 534 535 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { 536 /// Makes a new `MappedMutexGuard` for a component of the locked data. 537 /// 538 /// This operation cannot fail as the `MappedMutexGuard` passed 539 /// in already locked the mutex. 540 /// 541 /// This is an associated function that needs to be 542 /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of 543 /// the same name on the contents of the locked data. 544 #[inline] map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U> where F: FnOnce(&mut T) -> &mut U,545 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U> 546 where 547 F: FnOnce(&mut T) -> &mut U, 548 { 549 let raw = s.raw; 550 let data = f(unsafe { &mut *s.data }); 551 mem::forget(s); 552 MappedMutexGuard { 553 raw, 554 data, 555 marker: PhantomData, 556 } 557 } 558 559 /// Attempts to make a new `MappedMutexGuard` for a component of the 560 /// locked data. The original guard is returned if the closure returns `None`. 561 /// 562 /// This operation cannot fail as the `MappedMutexGuard` passed 563 /// in already locked the mutex. 564 /// 565 /// This is an associated function that needs to be 566 /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of 567 /// the same name on the contents of the locked data. 568 #[inline] try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>,569 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self> 570 where 571 F: FnOnce(&mut T) -> Option<&mut U>, 572 { 573 let raw = s.raw; 574 let data = match f(unsafe { &mut *s.data }) { 575 Some(data) => data, 576 None => return Err(s), 577 }; 578 mem::forget(s); 579 Ok(MappedMutexGuard { 580 raw, 581 data, 582 marker: PhantomData, 583 }) 584 } 585 } 586 587 impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> { 588 /// Unlocks the mutex using a fair unlock protocol. 589 /// 590 /// By default, mutexes are unfair and allow the current thread to re-lock 591 /// the mutex before another has the chance to acquire the lock, even if 592 /// that thread has been blocked on the mutex for a long time. This is the 593 /// default because it allows much higher throughput as it avoids forcing a 594 /// context switch on every mutex unlock. This can result in one thread 595 /// acquiring a mutex many more times than other threads. 596 /// 597 /// However in some cases it can be beneficial to ensure fairness by forcing 598 /// the lock to pass on to a waiting thread if there is one. This is done by 599 /// using this method instead of dropping the `MutexGuard` normally. 600 #[inline] unlock_fair(s: Self)601 pub fn unlock_fair(s: Self) { 602 s.raw.unlock_fair(); 603 mem::forget(s); 604 } 605 } 606 607 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> { 608 type Target = T; 609 #[inline] deref(&self) -> &T610 fn deref(&self) -> &T { 611 unsafe { &*self.data } 612 } 613 } 614 615 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> { 616 #[inline] deref_mut(&mut self) -> &mut T617 fn deref_mut(&mut self) -> &mut T { 618 unsafe { &mut *self.data } 619 } 620 } 621 622 impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> { 623 #[inline] drop(&mut self)624 fn drop(&mut self) { 625 self.raw.unlock(); 626 } 627 } 628 629 impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result630 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 631 fmt::Debug::fmt(&**self, f) 632 } 633 } 634 635 impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display 636 for MappedMutexGuard<'a, R, T> 637 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result638 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 639 (**self).fmt(f) 640 } 641 } 642 643 #[cfg(feature = "owning_ref")] 644 unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {} 645