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