### WebKit Queue Integration Test Setup Source: https://docs.rs/parking_lot/latest/src/parking_lot/condvar.rs.html?search=std%3A%3Avec Setup structures for a WebKit-inspired integration test for Condvar. ```rust #[derive(Clone, Copy)] enum Timeout { Bounded(Duration), Forever, } #[derive(Clone, Copy)] enum NotifyStyle { One, All, } struct Queue { items: VecDeque, should_continue: bool, } impl Queue { fn new() -> Self { Self { items: VecDeque::new(), should_continue: true, } } } fn wait( condition: &Condvar, ``` -------------------------------- ### Trait Implementations and Debugging Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Examples showing Sync implementation, Debug formatting, and Serde serialization. ```rust #[test] fn test_mutexguard_sync() { fn sync(_: T) {} let mutex = FairMutex::new(()); sync(mutex.lock()); } #[test] fn test_mutex_debug() { let mutex = FairMutex::new(vec![0u8, 10]); assert_eq!(format!("{:?}", mutex), "Mutex { data: [0, 10] }"); let _lock = mutex.lock(); assert_eq!(format!("{:?}", mutex), "Mutex { data: }"); } #[cfg(feature = "serde")] #[test] fn test_serde() { let contents: Vec = vec![0, 1, 2]; let mutex = FairMutex::new(contents.clone()); let serialized = serialize(&mutex).unwrap(); let deserialized: FairMutex> = deserialize(&serialized).unwrap(); assert_eq!(*(mutex.lock()), *(deserialized.lock())); assert_eq!(contents, *(deserialized.lock())); } ``` -------------------------------- ### Queue Test Suite Invocation Source: https://docs.rs/parking_lot/latest/src/parking_lot/condvar.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Example usage of the run_queue_tests macro to define various test scenarios. ```rust run_queue_tests! { sanity_check_queue( num_producers: 1, num_consumers: 1, max_queue_size: 1, messages_per_producer: 100_000, notification_style: NotifyStyle::All, timeout: Timeout::Bounded(Duration::from_secs(1)), delay_seconds: 0 ); sanity_check_queue_timeout( num_producers: 1, num_consumers: 1, max_queue_size: 1, messages_per_producer: 100_000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); new_test_without_timeout_5( num_producers: 1, num_consumers: 5, max_queue_size: 1, messages_per_producer: 100_000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); one_producer_one_consumer_one_slot( num_producers: 1, num_consumers: 1, max_queue_size: 1, messages_per_producer: 100_000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); one_producer_one_consumer_one_slot_timeout( num_producers: 1, num_consumers: 1, max_queue_size: 1, messages_per_producer: 100_000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 1 ); one_producer_one_consumer_hundred_slots( num_producers: 1, num_consumers: 1, max_queue_size: 100, messages_per_producer: 1_000_000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); ten_producers_one_consumer_one_slot( num_producers: 10, num_consumers: 1, max_queue_size: 1, messages_per_producer: 10000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); ten_producers_one_consumer_hundred_slots_notify_all( num_producers: 10, num_consumers: 1, max_queue_size: 100, messages_per_producer: 10000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); ten_producers_one_consumer_hundred_slots_notify_one( num_producers: 10, num_consumers: 1, max_queue_size: 100, messages_per_producer: 10000, notification_style: NotifyStyle::One, timeout: Timeout::Forever, delay_seconds: 0 ); one_producer_ten_consumers_one_slot( num_producers: 1, num_consumers: 10, max_queue_size: 1, messages_per_producer: 100_000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); ``` -------------------------------- ### FairMutex Interior Mutability and Ownership Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html?search= Examples showing how to extract inner values or access mutable references directly. ```rust #[test] fn test_into_inner() { let m = FairMutex::new(NonCopy(10)); assert_eq!(m.into_inner(), NonCopy(10)); } #[test] fn test_into_inner_drop() { struct Foo(Arc); impl Drop for Foo { fn drop(&mut self) { self.0.fetch_add(1, Ordering::SeqCst); } } let num_drops = Arc::new(AtomicUsize::new(0)); let m = FairMutex::new(Foo(num_drops.clone())); assert_eq!(num_drops.load(Ordering::SeqCst), 0); { let _inner = m.into_inner(); assert_eq!(num_drops.load(Ordering::SeqCst), 0); } assert_eq!(num_drops.load(Ordering::SeqCst), 1); } #[test] fn test_get_mut() { let mut m = FairMutex::new(NonCopy(10)); *m.get_mut() = NonCopy(20); assert_eq!(m.into_inner(), NonCopy(20)); } ``` -------------------------------- ### FairMutex Ownership and Mutation Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html Examples of consuming the mutex or accessing the inner value mutably. ```rust #[test] fn test_into_inner() { let m = FairMutex::new(NonCopy(10)); assert_eq!(m.into_inner(), NonCopy(10)); } ``` ```rust #[test] fn test_into_inner_drop() { struct Foo(Arc); impl Drop for Foo { fn drop(&mut self) { self.0.fetch_add(1, Ordering::SeqCst); } } let num_drops = Arc::new(AtomicUsize::new(0)); let m = FairMutex::new(Foo(num_drops.clone())); assert_eq!(num_drops.load(Ordering::SeqCst), 0); { let _inner = m.into_inner(); assert_eq!(num_drops.load(Ordering::SeqCst), 0); } assert_eq!(num_drops.load(Ordering::SeqCst), 1); } ``` ```rust #[test] fn test_get_mut() { let mut m = FairMutex::new(NonCopy(10)); *m.get_mut() = NonCopy(20); assert_eq!(m.into_inner(), NonCopy(20)); } ``` -------------------------------- ### Internal Wait-While Logic Source: https://docs.rs/parking_lot/latest/src/parking_lot/condvar.rs.html?search=std%3A%3Avec Examples of using wait_while_until_internal to block until a condition is met or a timeout occurs. ```rust #[test] fn wait_while_until_internal_does_not_wait_if_initially_false() { let mutex = Arc::new(Mutex::new(0)); let cv = Arc::new(Condvar::new()); let condition = |counter: &mut u32| { *counter += 1; false }; let mut mutex_guard = mutex.lock(); let timeout_result = cv.wait_while_until_internal(&mut mutex_guard, condition, None); assert!(!timeout_result.timed_out()); assert!(*mutex_guard == 1); } ``` ```rust #[test] fn wait_while_until_internal_times_out_before_false() { let mutex = Arc::new(Mutex::new(0)); let cv = Arc::new(Condvar::new()); let num_iters = 3; let condition = |counter: &mut u32| { *counter += 1; true }; let mut mutex_guard = mutex.lock(); let timeout = Some(Instant::now() + Duration::from_millis(500)); let handle = spawn_wait_while_notifier(mutex.clone(), cv.clone(), num_iters, timeout); let timeout_result = cv.wait_while_until_internal(&mut mutex_guard, condition, timeout); assert!(timeout_result.timed_out()); assert!(*mutex_guard == num_iters + 1); // prevent deadlock with notifier drop(mutex_guard); handle.join().unwrap(); } ``` -------------------------------- ### Once::call_once_force() Source: https://docs.rs/parking_lot/latest/parking_lot/struct.Once.html Performs an initialization routine, ignoring poisoning. ```APIDOC ## pub fn call_once_force(&self, f: F) where F: FnOnce(OnceState) ### Description Performs the same function as `call_once` except it ignores poisoning. If the `Once` has been poisoned, this function will continue to attempt initialization until one succeeds. ``` -------------------------------- ### Once::call_once() Source: https://docs.rs/parking_lot/latest/parking_lot/struct.Once.html Performs an initialization routine exactly once. ```APIDOC ## pub fn call_once(&self, f: F) where F: FnOnce() ### Description Performs an initialization routine once and only once. The given closure will be executed if this is the first time `call_once` has been called. If the closure panics, the `Once` instance becomes poisoned. ``` -------------------------------- ### Get Mut Test Source: https://docs.rs/parking_lot/latest/src/parking_lot/mutex.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Verifies mutable access to the inner value when the mutex is uniquely held. ```rust #[test] fn test_get_mut() { let mut m = Mutex::new(NonCopy(10)); *m.get_mut() = NonCopy(20); assert_eq!(m.into_inner(), NonCopy(20)); } ``` -------------------------------- ### Basic RwLock Usage Source: https://docs.rs/parking_lot/latest/parking_lot/type.RwLock.html Demonstrates standard read and write locking patterns using RwLock. ```rust use parking_lot::RwLock; let lock = RwLock::new(5); // many reader locks can be held at once { let r1 = lock.read(); let r2 = lock.read(); assert_eq!(*r1, 5); assert_eq!(*r2, 5); } // read locks are dropped at this point // only one write lock may be held, however { let mut w = lock.write(); *w += 1; assert_eq!(*w, 6); } // write lock is dropped here ``` -------------------------------- ### Advanced Synchronization Scenarios Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates nested mutexes, handling panics during drops, and working with unsized types. ```rust #[test] fn test_mutex_arc_nested() { // Tests nested mutexes and access // to underlying data. let arc = Arc::new(FairMutex::new(1)); let arc2 = Arc::new(FairMutex::new(arc)); let (tx, rx) = channel(); let _t = thread::spawn(move || { let lock = arc2.lock(); let lock2 = lock.lock(); assert_eq!(*lock2, 1); tx.send(()).unwrap(); }); rx.recv().unwrap(); } #[test] fn test_mutex_arc_access_in_unwind() { let arc = Arc::new(FairMutex::new(1)); let arc2 = arc.clone(); let _ = thread::spawn(move || { struct Unwinder { i: Arc>, } impl Drop for Unwinder { fn drop(&mut self) { *self.i.lock() += 1; } } let _u = Unwinder { i: arc2 }; panic!(); }) .join(); let lock = arc.lock(); assert_eq!(*lock, 2); } #[test] fn test_mutex_unsized() { let mutex: &FairMutex<[i32]> = &FairMutex::new([1, 2, 3]); { let b = &mut *mutex.lock(); b[0] = 4; b[2] = 5; } let comp: &[i32] = &[4, 2, 5]; assert_eq!(&*mutex.lock(), comp); } ``` -------------------------------- ### Try Lock and Inner Data Access Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html?search=std%3A%3Avec Examples of using try_lock and accessing the inner data of a FairMutex. ```rust #[test] fn try_lock() { let m = FairMutex::new(()); *m.try_lock().unwrap() = (); } #[test] fn test_into_inner() { let m = FairMutex::new(NonCopy(10)); assert_eq!(m.into_inner(), NonCopy(10)); } #[test] fn test_into_inner_drop() { struct Foo(Arc); impl Drop for Foo { fn drop(&mut self) { self.0.fetch_add(1, Ordering::SeqCst); } } let num_drops = Arc::new(AtomicUsize::new(0)); let m = FairMutex::new(Foo(num_drops.clone())); assert_eq!(num_drops.load(Ordering::SeqCst), 0); { let _inner = m.into_inner(); assert_eq!(num_drops.load(Ordering::SeqCst), 0); } assert_eq!(num_drops.load(Ordering::SeqCst), 1); } #[test] fn test_get_mut() { let mut m = FairMutex::new(NonCopy(10)); *m.get_mut() = NonCopy(20); assert_eq!(m.into_inner(), NonCopy(20)); } ``` -------------------------------- ### Once::new() Source: https://docs.rs/parking_lot/latest/parking_lot/struct.Once.html Creates a new Once instance. ```APIDOC ## pub const fn new() -> Once ### Description Creates a new `Once` value. ``` -------------------------------- ### Serde Serialization Support Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html?search=std%3A%3Avec Demonstrates serialization and deserialization of a FairMutex when the serde feature is enabled. ```rust #[cfg(feature = "serde")] #[test] fn test_serde() { let contents: Vec = vec![0, 1, 2]; let mutex = FairMutex::new(contents.clone()); let serialized = serialize(&mutex).unwrap(); let deserialized: FairMutex> = deserialize(&serialized).unwrap(); assert_eq!(*(mutex.lock()), *(deserialized.lock())); assert_eq!(contents, *(deserialized.lock())); } ``` -------------------------------- ### Get non-zero thread ID Source: https://docs.rs/parking_lot/latest/parking_lot/struct.RawThreadId.html?search= Retrieves a non-zero thread ID identifying the current execution thread. ```rust fn nonzero_thread_id(&self) -> NonZeroUsize ``` -------------------------------- ### Test wait_until functionality Source: https://docs.rs/parking_lot/latest/src/parking_lot/condvar.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates using wait_until with an Instant deadline. ```rust #[test] fn wait_until() { let m = Arc::new(Mutex::new(())); let m2 = m.clone(); let c = Arc::new(Condvar::new()); let c2 = c.clone(); let mut g = m.lock(); let no_timeout = c.wait_until(&mut g, Instant::now() + Duration::from_millis(1)); assert!(no_timeout.timed_out()); let _t = thread::spawn(move || { let _g = m2.lock(); c2.notify_one(); }); let timeout_res = c.wait_until( &mut g, Instant::now() + Duration::from_millis(u32::max_value() as u64), ); assert!(!timeout_res.timed_out()); drop(g); } ``` -------------------------------- ### Unlock Fairly Source: https://docs.rs/parking_lot/latest/parking_lot/type.MappedReentrantMutexGuard.html?search= Unlocks the mutex using a fair protocol to ensure waiting threads get a chance to acquire the lock. ```rust pub fn unlock_fair(s: MappedReentrantMutexGuard<'a, R, G, T>) ``` -------------------------------- ### FairMutex Trait Implementations Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html Demonstrates Sync, Debug, and Serde support. ```rust #[test] fn test_mutexguard_sync() { fn sync(_: T) {} let mutex = FairMutex::new(()); sync(mutex.lock()); } ``` ```rust #[test] fn test_mutex_debug() { let mutex = FairMutex::new(vec![0u8, 10]); assert_eq!(format!("{:?}", mutex), "Mutex { data: [0, 10] }"); let _lock = mutex.lock(); assert_eq!(format!("{:?}", mutex), "Mutex { data: }"); } ``` ```rust #[cfg(feature = "serde")] #[test] fn test_serde() { let contents: Vec = vec![0, 1, 2]; let mutex = FairMutex::new(contents.clone()); let serialized = serialize(&mutex).unwrap(); let deserialized: FairMutex> = deserialize(&serialized).unwrap(); assert_eq!(*(mutex.lock()), *(deserialized.lock())); assert_eq!(contents, *(deserialized.lock())); } ``` -------------------------------- ### Multi-threaded Mutex Usage Source: https://docs.rs/parking_lot/latest/src/parking_lot/mutex.rs.html?search=std%3A%3Avec Examples of using Mutex with Arc across multiple threads, including nested mutexes and condition variables. ```rust #[test] fn lots_and_lots() { const J: u32 = 1000; const K: u32 = 3; let m = Arc::new(Mutex::new(0)); fn inc(m: &Mutex) { for _ in 0..J { *m.lock() += 1; } } let (tx, rx) = channel(); for _ in 0..K { let tx2 = tx.clone(); let m2 = m.clone(); thread::spawn(move || { inc(&m2); tx2.send(()).unwrap(); }); let tx2 = tx.clone(); let m2 = m.clone(); thread::spawn(move || { inc(&m2); tx2.send(()).unwrap(); }); } drop(tx); for _ in 0..2 * K { rx.recv().unwrap(); } assert_eq!(*m.lock(), J * K * 2); } ``` ```rust #[test] fn test_mutex_arc_condvar() { let packet = Packet(Arc::new((Mutex::new(false), Condvar::new()))); let packet2 = Packet(packet.0.clone()); let (tx, rx) = channel(); let _t = thread::spawn(move || { // wait until parent gets in rx.recv().unwrap(); let (lock, cvar) = &*packet2.0; let mut lock = lock.lock(); *lock = true; cvar.notify_one(); }); let (lock, cvar) = &*packet.0; let mut lock = lock.lock(); tx.send(()).unwrap(); assert!(!*lock); while !*lock { cvar.wait(&mut lock); } } ``` ```rust #[test] fn test_mutex_arc_nested() { // Tests nested mutexes and access // to underlying data. let arc = Arc::new(Mutex::new(1)); let arc2 = Arc::new(Mutex::new(arc)); let (tx, rx) = channel(); let _t = thread::spawn(move || { let lock = arc2.lock(); let lock2 = lock.lock(); assert_eq!(*lock2, 1); tx.send(()).unwrap(); }); rx.recv().unwrap(); } ``` -------------------------------- ### Basic FairMutex Operations Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html Demonstrates basic locking and try_lock functionality. ```rust #[test] fn smoke() { let m = FairMutex::new(()); drop(m.lock()); drop(m.lock()); } ``` ```rust #[test] fn try_lock() { let m = FairMutex::new(()); *m.try_lock().unwrap() = (); } ``` -------------------------------- ### Unlock MappedMutexGuard fairly Source: https://docs.rs/parking_lot/latest/parking_lot/type.MappedFairMutexGuard.html?search= Unlocks the mutex using a fair unlock protocol to ensure waiting threads get a chance to acquire the lock. ```rust pub fn unlock_fair(s: MappedMutexGuard<'a, R, T>) ``` -------------------------------- ### Basic Mutex Operations Source: https://docs.rs/parking_lot/latest/src/parking_lot/mutex.rs.html?search=std%3A%3Avec Demonstrates basic locking, try_lock, and ownership-based access methods. ```rust #[test] fn smoke() { let m = Mutex::new(()); drop(m.lock()); drop(m.lock()); } ``` ```rust #[test] fn try_lock() { let m = Mutex::new(()); *m.try_lock().unwrap() = (); } ``` ```rust #[test] fn test_into_inner() { let m = Mutex::new(NonCopy(10)); assert_eq!(m.into_inner(), NonCopy(10)); } ``` ```rust #[test] fn test_get_mut() { let mut m = Mutex::new(NonCopy(10)); *m.get_mut() = NonCopy(20); assert_eq!(m.into_inner(), NonCopy(20)); } ``` -------------------------------- ### Library Module and Export Definitions Source: https://docs.rs/parking_lot/latest/src/parking_lot/lib.rs.html?search= The main entry point for the parking_lot crate, defining modules and re-exporting synchronization primitives. ```rust 1// Copyright 2016 Amanieu d'Antras 2// 3// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8//! This library provides implementations of `Mutex`, `RwLock`, `Condvar` and 9//! `Once` that are smaller, faster and more flexible than those in the Rust 10//! standard library. It also provides a `ReentrantMutex` type. 11 12#![warn(missing_docs)] 13#![warn(rust_2018_idioms)] 14 15mod condvar; 16mod elision; 17mod fair_mutex; 18mod mutex; 19mod once; 20mod raw_fair_mutex; 21mod raw_mutex; 22mod raw_rwlock; 23mod remutex; 24mod rwlock; 25mod util; 26 27#[cfg(feature = "deadlock_detection")] 28pub mod deadlock; 29#[cfg(not(feature = "deadlock_detection"))] 30mod deadlock; 31 32// If deadlock detection is enabled, we cannot allow lock guards to be sent to 33// other threads. 34#[cfg(all(feature = "send_guard", feature = "deadlock_detection"))] 35compile_error!("the `send_guard` and `deadlock_detection` features cannot be used together"); 36#[cfg(feature = "send_guard")] 37type GuardMarker = lock_api::GuardSend; 38#[cfg(not(feature = "send_guard"))] 39type GuardMarker = lock_api::GuardNoSend; 40 41pub use self::condvar::{Condvar, WaitTimeoutResult}; 42pub use self::fair_mutex::{const_fair_mutex, FairMutex, FairMutexGuard, MappedFairMutexGuard}; 43pub use self::mutex::{const_mutex, MappedMutexGuard, Mutex, MutexGuard}; 44pub use self::once::{Once, OnceState}; 45pub use self::raw_fair_mutex::RawFairMutex; 46pub use self::raw_mutex::RawMutex; 47pub use self::raw_rwlock::RawRwLock; 48pub use self::remutex::{ 49 const_reentrant_mutex, MappedReentrantMutexGuard, RawThreadId, ReentrantMutex, 50 ReentrantMutexGuard, 51}; 52pub use self::rwlock::{ 53 const_rwlock, MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, 54 RwLockUpgradableReadGuard, RwLockWriteGuard, 55}; 56pub use ::lock_api; 57 58#[cfg(feature = "arc_lock")] 59pub use self::lock_api::{ 60 ArcMutexGuard, ArcReentrantMutexGuard, ArcRwLockReadGuard, ArcRwLockUpgradableReadGuard, 61 ArcRwLockWriteGuard, 62}; ``` -------------------------------- ### ReentrantMutex Raw Initialization Methods Source: https://docs.rs/parking_lot/latest/parking_lot/type.ReentrantMutex.html Methods for creating a ReentrantMutex from raw components, including constant context support. ```rust pub const fn from_raw( raw_mutex: R, get_thread_id: G, val: T, ) -> ReentrantMutex ``` ```rust pub const fn const_new( raw_mutex: R, get_thread_id: G, val: T, ) -> ReentrantMutex ``` -------------------------------- ### RwLock::new Source: https://docs.rs/parking_lot/latest/parking_lot/type.RwLock.html?search= Creates a new instance of an RwLock which is unlocked. ```APIDOC ## pub const fn new(val: T) -> RwLock ### Description Creates a new instance of an `RwLock` which is unlocked. ``` -------------------------------- ### Basic FairMutex Operations Source: https://docs.rs/parking_lot/latest/src/parking_lot/fair_mutex.rs.html?search=std%3A%3Avec Demonstrates basic locking and concurrent increment operations using FairMutex. ```rust #[derive(Eq, PartialEq, Debug)] struct NonCopy(i32); #[test] fn smoke() { let m = FairMutex::new(()); drop(m.lock()); drop(m.lock()); } #[test] fn lots_and_lots() { const J: u32 = 1000; const K: u32 = 3; let m = Arc::new(FairMutex::new(0)); fn inc(m: &FairMutex) { for _ in 0..J { *m.lock() += 1; } } let (tx, rx) = channel(); for _ in 0..K { let tx2 = tx.clone(); let m2 = m.clone(); thread::spawn(move || { inc(&m2); tx2.send(()).unwrap(); }); let tx2 = tx.clone(); let m2 = m.clone(); thread::spawn(move || { inc(&m2); tx2.send(()).unwrap(); }); } drop(tx); for _ in 0..2 * K { rx.recv().unwrap(); } assert_eq!(*m.lock(), J * K * 2); } ``` -------------------------------- ### RawRwLock State Transition and Slow Path Methods Source: https://docs.rs/parking_lot/latest/src/parking_lot/raw_rwlock.rs.html Internal methods for handling lock upgrades, downgrades, and state adjustments when the fast path fails. ```rust loop { if state & READERS_MASK != ONE_READER { return false; } match self.state.compare_exchange_weak( state, state - (ONE_READER | UPGRADABLE_BIT) + WRITER_BIT, Ordering::Relaxed, Ordering::Relaxed, ) { Ok(_) => return true, Err(x) => state = x, } } } #[cold] fn upgrade_slow(&self, timeout: Option) -> bool { self.deadlock_release(); let result = self.wait_for_readers(timeout, ONE_READER | UPGRADABLE_BIT); self.deadlock_acquire(); result } #[cold] fn downgrade_slow(&self) { // We only reach this point if PARKED_BIT is set. let callback = |_, result: UnparkResult| { // Clear the parked bit if there no more parked threads if !result.have_more_threads { self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); } TOKEN_NORMAL }; // SAFETY: `callback` does not panic or call into any function of `parking_lot`. unsafe { self.wake_parked_threads(ONE_READER, callback); } } #[cold] fn downgrade_to_upgradable_slow(&self) { // We only reach this point if PARKED_BIT is set. let callback = |_, result: UnparkResult| { // Clear the parked bit if there no more parked threads if !result.have_more_threads { self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); } TOKEN_NORMAL }; // SAFETY: `callback` does not panic or call into any function of `parking_lot`. unsafe { self.wake_parked_threads(ONE_READER | UPGRADABLE_BIT, callback); } } #[cold] unsafe fn bump_shared_slow(&self) { self.unlock_shared(); self.lock_shared(); } #[cold] fn bump_exclusive_slow(&self) { self.deadlock_release(); self.unlock_exclusive_slow(true); self.lock_exclusive(); } #[cold] fn bump_upgradable_slow(&self) { self.deadlock_release(); self.unlock_upgradable_slow(true); self.lock_upgradable(); } ``` -------------------------------- ### Library Module and Export Definitions Source: https://docs.rs/parking_lot/latest/src/parking_lot/lib.rs.html Core module structure and public API exports for the parking_lot crate. ```rust 1// Copyright 2016 Amanieu d'Antras 2// 3// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8//! This library provides implementations of `Mutex`, `RwLock`, `Condvar` and 9//! `Once` that are smaller, faster and more flexible than those in the Rust 10//! standard library. It also provides a `ReentrantMutex` type. 11 12#![warn(missing_docs)] 13#![warn(rust_2018_idioms)] 14 15mod condvar; 16mod elision; 17mod fair_mutex; 18mod mutex; 19mod once; 20mod raw_fair_mutex; 21mod raw_mutex; 22mod raw_rwlock; 23mod remutex; 24mod rwlock; 25mod util; 26 27#[cfg(feature = "deadlock_detection")] 28pub mod deadlock; 29#[cfg(not(feature = "deadlock_detection"))] 30mod deadlock; 31 32// If deadlock detection is enabled, we cannot allow lock guards to be sent to 33// other threads. 34#[cfg(all(feature = "send_guard", feature = "deadlock_detection"))] 35compile_error!("the `send_guard` and `deadlock_detection` features cannot be used together"); 36#[cfg(feature = "send_guard")] 37type GuardMarker = lock_api::GuardSend; 38#[cfg(not(feature = "send_guard"))] 39type GuardMarker = lock_api::GuardNoSend; 40 41pub use self::condvar::{Condvar, WaitTimeoutResult}; 42pub use self::fair_mutex::{const_fair_mutex, FairMutex, FairMutexGuard, MappedFairMutexGuard}; 43pub use self::mutex::{const_mutex, MappedMutexGuard, Mutex, MutexGuard}; 44pub use self::once::{Once, OnceState}; 45pub use self::raw_fair_mutex::RawFairMutex; 46pub use self::raw_mutex::RawMutex; 47pub use self::raw_rwlock::RawRwLock; 48pub use self::remutex::{ 49 const_reentrant_mutex, MappedReentrantMutexGuard, RawThreadId, ReentrantMutex, 50 ReentrantMutexGuard, 51}; 52pub use self::rwlock::{ 53 const_rwlock, MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, 54 RwLockUpgradableReadGuard, RwLockWriteGuard, 55}; 56pub use ::lock_api; 57 58#[cfg(feature = "arc_lock")] 59pub use self::lock_api::{ 60 ArcMutexGuard, ArcReentrantMutex, ArcRwLockReadGuard, ArcRwLockUpgradableReadGuard, 61 ArcRwLockWriteGuard, 62}; ``` -------------------------------- ### Mutex initialization and consumption methods Source: https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Methods for creating a new Mutex or consuming it to retrieve the inner data. ```rust pub const fn new(val: T) -> Mutex ``` ```rust pub fn into_inner(self) -> T ``` -------------------------------- ### Configure Condvar Benchmark Scenarios Source: https://docs.rs/parking_lot/latest/src/parking_lot/condvar.rs.html These function calls define parameters for producer-consumer benchmarks, including queue capacity, message counts, and notification styles. ```rust num_consumers: 10, max_queue_size: 1, messages_per_producer: 10000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); one_producer_ten_consumers_hundred_slots_notify_all( num_producers: 1, num_consumers: 10, max_queue_size: 100, messages_per_producer: 100_000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); one_producer_ten_consumers_hundred_slots_notify_one( num_producers: 1, num_consumers: 10, max_queue_size: 100, messages_per_producer: 100_000, notification_style: NotifyStyle::One, timeout: Timeout::Forever, delay_seconds: 0 ); ten_producers_ten_consumers_one_slot( num_producers: 10, num_consumers: 10, max_queue_size: 1, messages_per_producer: 50000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); ten_producers_ten_consumers_hundred_slots_notify_all( num_producers: 10, num_consumers: 10, max_queue_size: 100, messages_per_producer: 50000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); ten_producers_ten_consumers_hundred_slots_notify_one( num_producers: 10, num_consumers: 10, max_queue_size: 100, messages_per_producer: 50000, notification_style: NotifyStyle::One, timeout: Timeout::Forever, delay_seconds: 0 ); } } ``` -------------------------------- ### try_upgradable_read Source: https://docs.rs/parking_lot/latest/parking_lot/type.RwLock.html Attempts to acquire the RwLock with upgradable read access without blocking. ```APIDOC ## pub fn try_upgradable_read(&self) -> Option> ### Description Attempts to acquire this `RwLock` with upgradable read access. If the access could not be granted at this time, then `None` is returned. Otherwise, an RAII guard is returned. ``` -------------------------------- ### RwLockUpgradableReadGuard methods Source: https://docs.rs/parking_lot/latest/parking_lot/type.RwLockUpgradableReadGuard.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Methods for interacting with the RwLockUpgradableReadGuard, including upgrading, downgrading, and fair unlocking. ```rust pub fn rwlock(s: &RwLockUpgradableReadGuard<'a, R, T>) -> &'a RwLock ``` ```rust pub fn unlocked(s: &mut RwLockUpgradableReadGuard<'a, R, T>, f: F) -> U where F: FnOnce() -> U, ``` ```rust pub fn upgrade( s: RwLockUpgradableReadGuard<'a, R, T>, ) -> RwLockWriteGuard<'a, R, T> ``` ```rust pub fn try_upgrade( s: RwLockUpgradableReadGuard<'a, R, T>, ) -> Result, RwLockUpgradableReadGuard<'a, R, T>> ``` ```rust pub fn unlock_fair(s: RwLockUpgradableReadGuard<'a, R, T>) ``` ```rust pub fn unlocked_fair( s: &mut RwLockUpgradableReadGuard<'a, R, T>, f: F, ) -> U where F: FnOnce() -> U, ``` ```rust pub fn bump(s: &mut RwLockUpgradableReadGuard<'a, R, T>) ``` ```rust pub fn downgrade( s: RwLockUpgradableReadGuard<'a, R, T>, ) -> RwLockReadGuard<'a, R, T> ``` ```rust pub fn with_upgraded(&mut self, f: F) -> Ret where F: FnOnce(&mut T) -> Ret, ``` ```rust pub fn try_with_upgraded(&mut self, f: F) -> Option where F: FnOnce(&mut T) -> Ret, ``` -------------------------------- ### Mutex::new Source: https://docs.rs/parking_lot/latest/parking_lot/type.FairMutex.html?search=u32+-%3E+bool Creates a new mutex in an unlocked state ready for use. ```APIDOC ## pub const fn new(val: T) -> Mutex ### Description Creates a new mutex in an unlocked state ready for use. ``` -------------------------------- ### into_arc_fair Source: https://docs.rs/parking_lot/latest/parking_lot/struct.ArcRwLockWriteGuard.html?search= Unlocks the RwLock using a fair protocol and returns the Arc. ```APIDOC ### pub fn into_arc_fair(s: ArcRwLockWriteGuard) -> Arc> Unlocks the `RwLock` using a fair unlock protocol and returns the `Arc` that was held by the `ArcRwLockWriteGuard`. ``` -------------------------------- ### Implement AtomicElisionExt for AtomicUsize Source: https://docs.rs/parking_lot/latest/src/parking_lot/elision.rs.html Provides the implementation for AtomicUsize, using unreachable code for unsupported platforms and assembly for supported x86 targets. ```rust #[cfg(not(all( feature = "hardware-lock-elision", not(miri), any(target_arch = "x86", target_arch = "x86_64") )))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; #[inline] fn elision_compare_exchange_acquire(&self, _: usize, _: usize) -> Result { unreachable!(); } #[inline] fn elision_fetch_sub_release(&self, _: usize) -> usize { unreachable!(); } } ``` ```rust #[cfg(all( feature = "hardware-lock-elision", not(miri), any(target_arch = "x86", target_arch = "x86_64") ))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; #[inline] fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result { unsafe { use core::arch::asm; let prev: usize; #[cfg(target_pointer_width = "32")] asm!( "xacquire", "lock", "cmpxchg [{:e}], {:e}", in(reg) self, in(reg) new, inout("eax") current => prev, ); #[cfg(target_pointer_width = "64")] asm!( "xacquire", "lock", "cmpxchg [{}], {}", in(reg) self, in(reg) new, inout("rax") current => prev, ); if prev == current { Ok(prev) } else { Err(prev) } } } #[inline] fn elision_fetch_sub_release(&self, val: usize) -> usize { unsafe { use core::arch::asm; let prev: usize; #[cfg(target_pointer_width = "32")] asm!( "xrelease", "lock", "xadd [{:e}], {:e}", in(reg) self, inout(reg) val.wrapping_neg() => prev, ); #[cfg(target_pointer_width = "64")] asm!( "xrelease", "lock", "xadd [{}], {}", in(reg) self, inout(reg) val.wrapping_neg() => prev, ); prev } } } ``` -------------------------------- ### Once unit tests Source: https://docs.rs/parking_lot/latest/src/parking_lot/once.rs.html?search= Test suite covering basic execution, stampede scenarios, and poison handling. ```rust #[test] fn smoke_once() { static O: Once = Once::new(); let mut a = 0; O.call_once(|| a += 1); assert_eq!(a, 1); O.call_once(|| a += 1); assert_eq!(a, 1); } ``` ```rust #[test] fn stampede_once() { static O: Once = Once::new(); static mut RUN: bool = false; let (tx, rx) = channel(); for _ in 0..10 { let tx = tx.clone(); thread::spawn(move || { for _ in 0..4 { thread::yield_now() } unsafe { O.call_once(|| { assert!(!RUN); RUN = true; }); assert!(RUN); } tx.send(()).unwrap(); }); } unsafe { O.call_once(|| { assert!(!RUN); RUN = true; }); assert!(RUN); } for _ in 0..10 { rx.recv().unwrap(); } } ``` ```rust #[test] fn poison_bad() { static O: Once = Once::new(); // poison the once let t = panic::catch_unwind(|| { O.call_once(|| panic!()); }); assert!(t.is_err()); // poisoning propagates let t = panic::catch_unwind(|| { O.call_once(|| {}); }); assert!(t.is_err()); // we can subvert poisoning, however let mut called = false; O.call_once_force(|p| { called = true; assert!(p.poisoned()) }); assert!(called); // once any success happens, we stop propagating the poison O.call_once(|| {}); } ``` ```rust #[test] fn wait_for_force_to_finish() { static O: Once = Once::new(); // poison the once let t = panic::catch_unwind(|| { O.call_once(|| panic!()); }); assert!(t.is_err()); // make sure someone's waiting inside the once via a force let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); let t1 = thread::spawn(move || { O.call_once_force(|p| { assert!(p.poisoned()); tx1.send(()).unwrap(); rx2.recv().unwrap(); }); }); rx1.recv().unwrap(); // put another waiter on the once let t2 = thread::spawn(|| { let mut called = false; O.call_once(|| { called = true; }); assert!(!called); }); tx2.send(()).unwrap(); } ``` -------------------------------- ### RwLock with Arc and Threading Source: https://docs.rs/parking_lot/latest/src/parking_lot/rwlock.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates using RwLock within an Arc to share mutable state across multiple threads, including reader/writer synchronization. ```rust let arc = Arc::new(RwLock::new(0)); let arc2 = arc.clone(); let (tx, rx) = channel(); thread::spawn(move || { let mut lock = arc2.write(); for _ in 0..10 { let tmp = *lock; *lock = -1; thread::yield_now(); *lock = tmp + 1; } tx.send(()).unwrap(); }); // Readers try to catch the writer in the act let mut children = Vec::new(); for _ in 0..5 { let arc3 = arc.clone(); children.push(thread::spawn(move || { let lock = arc3.read(); assert!(*lock >= 0); })); } // Wait for children to pass their asserts for r in children { assert!(r.join().is_ok()); } // Wait for writer to finish rx.recv().unwrap(); let lock = arc.read(); assert_eq!(*lock, 10); ``` -------------------------------- ### Serialize and Deserialize RwLock Source: https://docs.rs/parking_lot/latest/src/parking_lot/rwlock.rs.html Demonstrates how to serialize and deserialize an RwLock containing data when the serde feature is enabled. ```rust #[cfg(feature = "serde")] #[test] fn test_serde() { let contents: Vec = vec![0, 1, 2]; let mutex = RwLock::new(contents.clone()); let serialized = serialize(&mutex).unwrap(); let deserialized: RwLock> = deserialize(&serialized).unwrap(); assert_eq!(*(mutex.read()), *(deserialized.read())); assert_eq!(contents, *(deserialized.read())); } ``` -------------------------------- ### RwLock Methods Source: https://docs.rs/parking_lot/latest/parking_lot/type.RwLock.html Methods for interacting with the RwLock, including state checks and data access. ```APIDOC ## pub fn get_mut(&mut self) -> &mut T Returns a mutable reference to the underlying data. Since this call borrows the RwLock mutably, no actual locking needs to take place. ## pub fn is_locked(&self) -> bool Checks whether this RwLock is currently locked in any way. ## pub fn is_locked_exclusive(&self) -> bool Check if this RwLock is currently exclusively locked. ## pub fn data_ptr(&self) -> *mut T Returns a raw pointer to the underlying data. Useful for FFI when combined with mem::forget. ```