### Rust Basic Once::call_once Initialization Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/once.rs A simple example demonstrating how to use `parking_lot::Once` to ensure a block of code, such as an application's startup routine, is executed only once. ```Rust use parking_lot::Once; static START: Once = Once::new(); START.call_once(|| { // run initialization here }); ``` -------------------------------- ### Rust: Example Parking Test Macro Invocations Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/src/parking_lot_core/parking_lot.rs These are concrete examples of how the `test!` macro is used to define various parking and unparking test scenarios. Each entry specifies the test name and parameters like the number of repetitions, latches, delay, threads involved, and the count of single unparks, covering both 'fast' (zero delay) and delayed scenarios. ```Rust test! { unpark_all_one_fast( repeats: 1000, latches: 1, delay: 0, threads: 1, single_unparks: 0 ); unpark_all_hundred_fast( repeats: 100, latches: 1, delay: 0, threads: 100, single_unparks: 0 ); unpark_one_one_fast( repeats: 1000, latches: 1, delay: 0, threads: 1, single_unparks: 1 ); unpark_one_hundred_fast( repeats: 20, latches: 1, delay: 0, threads: 100, single_unparks: 100 ); unpark_one_fifty_then_fifty_all_fast( repeats: 50, latches: 1, delay: 0, threads: 100, single_unparks: 50 ); unpark_all_one( repeats: 100, latches: 1, delay: 10000, threads: 1, single_unparks: 0 ); unpark_all_hundred( repeats: 100, latches: 1, delay: 10000, threads: 100, single_unparks: 0 ); unpark_one_one( repeats: 10, latches: 1, delay: 10000, threads: 1, single_unparks: 1 ); unpark_one_fifty( repeats: 1, latches: 1, delay: 10000, threads: 50, single_unparks: 50 ); unpark_one_fifty_then_fifty_all( repeats: 2, latches: 1, delay: 10000, threads: 100, single_unparks: 50 ); hundred_unpark_all_one_fast( repeats: 100, latches: 100, delay: 0, threads: 1, single_unparks: 0 ); hundred_unpark_all_one( repeats: 1, latches: 100, delay: 10000, threads: 1, single_unparks: 0 ); } ``` -------------------------------- ### Initialize with parking_lot::Once Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.Once Demonstrates how to use the `Once` struct to perform a one-time initialization. The `call_once` method ensures the provided closure is executed only once, even with multiple calls, making it suitable for global setup or FFI. ```Rust use parking_lot::Once; static START: Once = Once::new(); START.call_once(|| { // run initialization here }); ``` -------------------------------- ### Rust: Example Test Cases for Concurrent Queue Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/condvar.rs This snippet shows various test configurations for a concurrent queue, defined using the `run_queue_tests!` macro. It includes tests for different producer/consumer counts, queue sizes, message volumes, notification styles, and timeout behaviors, demonstrating how to use the macro to set up comprehensive concurrency tests. ```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, ``` -------------------------------- ### Rust: WebKit-Inspired Condvar Queue Test Setup Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/condvar.rs This section introduces a module for an integration test inspired by WebKit's `Condvar` tests. It defines helper enums (`Timeout`, `NotifyStyle`) and a `Queue` struct, along with a `wait` function signature, setting up the context for more complex `Condvar` usage scenarios. ```Rust /// This module contains an integration test that is heavily inspired from WebKit's own integration /// tests for it's own Condvar. #[cfg(test)] mod webkit_queue_test { use crate::{Condvar, Mutex, MutexGuard}; use std::{collections::VecDeque, sync::Arc, thread, time::Duration}; #[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, lock: &mut MutexGuard<'_, T>, ``` -------------------------------- ### Rust Once::call_once for Lazy Static Initialization Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/once.rs An example illustrating how `Once::call_once` can be used to safely initialize a `static mut` variable, ensuring an expensive computation is performed only once and its result is cached for subsequent access. ```Rust use parking_lot::Once; static mut VAL: usize = 0; static INIT: Once = Once::new(); // Accessing a `static mut` is unsafe much of the time, but if we do so // in a synchronized fashion (e.g. write once or read all) then we're // good to go! // // This function will only call `expensive_computation` once, and will // otherwise always return the value returned from the first invocation. fn get_cached_val() -> usize { unsafe { INIT.call_once(|| { VAL = expensive_computation(); }); VAL } } fn expensive_computation() -> usize { // ... # 2 } ``` -------------------------------- ### Rust parking_lot::Condvar API Definition and Usage Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/condvar.rs Documents the `Condvar` struct, its purpose, and key differences from the standard library's `Condvar`. Includes a detailed example demonstrating how to use `Condvar` with a `Mutex` for thread synchronization, highlighting its no-spurious-wakeups guarantee. ```Rust pub struct Condvar { state: AtomicPtr, } ``` ```Rust use parking_lot::{Mutex, Condvar}; use std::sync::Arc; use std::thread; let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = pair.clone(); // Inside of our lock, spawn a new thread, and then wait for it to start thread::spawn(move|| { let &(ref lock, ref cvar) = &*pair2; let mut started = lock.lock(); *started = true; cvar.notify_one(); }); // wait for the thread to start up let &(ref lock, ref cvar) = &*pair; let mut started = lock.lock(); if !*started { cvar.wait(&mut started); } // Note that we used an if instead of a while loop above. This is only // possible because parking_lot's Condvar will never spuriously wake up. // This means that wait() will only return after notify_one or notify_all is // called. ``` -------------------------------- ### Set up a background thread for deadlock detection in Rust Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/deadlock.rs This example demonstrates how to enable and use the experimental `deadlock_detection` feature in `parking_lot`. It spawns a background thread that periodically checks for deadlocks (every 10 seconds) and prints information about any detected deadlocks, including thread IDs and backtraces. This feature requires the `deadlock_detection` cargo feature flag to be enabled. ```Rust #[cfg(feature = "deadlock_detection")] { // only for #[cfg] use std::thread; use std::time::Duration; use parking_lot::deadlock; // Create a background thread which checks for deadlocks every 10s thread::spawn(move || { loop { thread::sleep(Duration::from_secs(10)); let deadlocks = deadlock::check_deadlock(); if deadlocks.is_empty() { continue; } println!("{} deadlocks detected", deadlocks.len()); for (i, threads) in deadlocks.iter().enumerate() { println!("Deadlock #{}", i); for t in threads { println!("Thread Id {:#?}", t.thread_id()); println!("{:#?}", t.backtrace()); } } } }); } // only for #[cfg] ``` -------------------------------- ### Rust Condvar::notify_one Method and Example Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/condvar.rs Documents the `notify_one` method, which wakes up a single blocked thread on the condition variable. It returns `true` if a thread was woken up, `false` otherwise, and calls are not buffered. Includes an example demonstrating its usage and checking the return value. ```Rust use parking_lot::Condvar; let condvar = Condvar::new(); // do something with condvar, share it with other threads if !condvar.notify_one() { println!("Nobody was listening for this."); } ``` ```Rust pub fn notify_one(&self) -> bool { // Nothing to do if there are no waiting threads let state = self.state.load(Ordering::Relaxed); if state.is_null() { return false; } self.notify_one_slow(state) } ``` -------------------------------- ### Normalize Cycle in Rust Graph Traversal Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/src/parking_lot_core/parking_lot.rs Normalizes a given cycle (a sequence of nodes) by rotating it so that it starts with the 'smallest' (minimum) node. This ensures consistent representation of cycles regardless of their starting point, which is useful for unique cycle identification and comparison in graph algorithms. ```Rust fn normalize_cycle(input: &[T]) -> Vec { let min_pos = input .iter() .enumerate() .min_by_key(|&(_, &t)| t) .map(|(p, _)| p) .unwrap_or(0); input .iter() .cycle() .skip(min_pos) .take(input.len()) .cloned() .collect() } ``` -------------------------------- ### `Bucket::new` Constructor Implementation Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/src/parking_lot_core/parking_lot.rs Implements the constructor for `Bucket`, initializing its `WordLock`, empty thread queues, and a `FairTimeout` instance with the given timeout and seed. ```Rust impl Bucket { #[inline] pub fn new(timeout: TimeoutInstant, seed: u32) -> Self { Self { mutex: WordLock::new(), queue_head: Cell::new(ptr::null()), queue_tail: Cell::new(ptr::null()), fair_timeout: UnsafeCell::new(FairTimeout::new(timeout, seed)), } } } ``` -------------------------------- ### Rust: Using FairMutex for Shared Data Increment Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/fair_mutex.rs This example demonstrates how to use `parking_lot::FairMutex` to protect shared integer data across multiple threads. It shows the process of acquiring a lock with `data.lock()`, safely modifying the shared state, and implicitly releasing the lock when the RAII guard goes out of scope. The example uses `Arc` for shared ownership and `mpsc::channel` to synchronize completion. ```Rust use parking_lot::FairMutex; use std::sync::{Arc, mpsc::channel}; use std::thread; const N: usize = 10; // Spawn a few threads to increment a shared variable (non-atomically), and // let the main thread know once all increments are done. // // Here we're using an Arc to share memory among threads, and the data inside // the Arc is protected with a mutex. let data = Arc::new(FairMutex::new(0)); let (tx, rx) = channel(); for _ in 0..10 { let (data, tx) = (Arc::clone(&data), tx.clone()); thread::spawn(move || { // The shared state can only be accessed once the lock is held. // Our non-atomic increment is safe because we're the only thread // which can access the shared state when the lock is held. let mut data = data.lock(); *data += 1; if *data == N { tx.send(()).unwrap(); } // the lock is unlocked here when `data` goes out of scope. }); } rx.recv().unwrap(); ``` -------------------------------- ### `HashTable::new` Constructor Implementation Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/src/parking_lot_core/parking_lot.rs Implements the constructor for `HashTable`, which initializes a new hash table with a size based on the number of threads and a `LOAD_FACTOR`. It ensures the size is a power of two and initializes each bucket with a unique seed. ```Rust impl HashTable { #[inline] fn new(num_threads: usize, prev: *const HashTable) -> Box { let new_size = (num_threads * LOAD_FACTOR).next_power_of_two(); let hash_bits = 0usize.leading_zeros() - new_size.leading_zeros() - 1; let now = TimeoutInstant::now(); let mut entries = Vec::with_capacity(new_size); for i in 0..new_size { // We must ensure the seed is not zero entries.push(Bucket::new(now, i as u32 + 1)); } Box::new(HashTable { entries: entries.into_boxed_slice(), hash_bits, _prev: prev, }) } } ``` -------------------------------- ### Get Mutex from ArcMutexGuard Reference Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.ArcMutexGuard Returns a reference to the `Mutex` that this `ArcMutexGuard` is guarding. The `Mutex` is contained within its `Arc`. ```APIDOC pub fn mutex(s: &ArcMutexGuard) -> &Arc> ``` -------------------------------- ### UnparkToken Struct API Reference Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.UnparkToken Detailed API documentation for the `UnparkToken` struct, including its methods and trait implementations from the `parking_lot_core` crate. ```APIDOC struct UnparkToken: - Implements core::clone::Clone trait: - fn clone(&self) -> UnparkToken Description: Returns a copy of the value. - fn clone_from(&mut self, source: &Self) Description: Performs copy-assignment from `source`. - Implements core::fmt::Debug trait: - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result Description: Formats the value using the given formatter. - Implements core::cmp::PartialEq trait: - fn eq(&self, other: &UnparkToken) -> bool Description: Tests for `self` and `other` values to be equal, and is used by `==`. - fn ne(&self, other: &Rhs) -> bool Description: Tests for `!=`. The default implementation is almost always sufficient, and should not be overridden without very good reason. - Implements core::marker::Copy trait - Implements core::cmp::Eq trait - Implements core::marker::StructuralPartialEq trait - Auto Trait Implementations: - Implements core::marker::Freeze trait - Implements core::panic::unwind_safe::RefUnwindSafe trait - Implements core::marker::Send trait - Implements core::marker::Sync trait - Implements core::marker::Unpin trait ``` -------------------------------- ### parking_lot Functions API Reference Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/index Documentation for functions provided by the `parking_lot` crate, primarily focusing on constant initializers for synchronization primitives, allowing for compile-time initialization. ```APIDOC const_fair_mutex: Creates a new fair mutex in an unlocked state ready for use. const_mutex: Creates a new mutex in an unlocked state ready for use. const_reentrant_mutex: Creates a new reentrant mutex in an unlocked state ready for use. const_rwlock: Creates a new instance of an `RwLock` which is unlocked. ``` -------------------------------- ### Implement Any for T: Get TypeId Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.ParkToken Provides a blanket implementation of the `Any` trait for any type `T` that is `'static` and potentially unsized. This allows runtime type identification. ```APIDOC impl Any for T where T: 'static + ?Sized fn type_id(&self) -> TypeId Description: Gets the TypeId of self. ``` -------------------------------- ### Rust Once Synchronization Primitive and Constructor Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/once.rs Introduces the `Once` synchronization primitive for one-time initialization, highlighting its memory efficiency and performance benefits over the standard library `Once`. It also defines the `Once` struct and its `new` constructor. ```APIDOC /// A synchronization primitive which can be used to run a one-time /// initialization. Useful for one-time initialization for globals, FFI or /// related functionality. /// /// # Differences from the standard library `Once` /// /// - Only requires 1 byte of space, instead of 1 word. /// - Not required to be `'static`. /// - Relaxed memory barriers in the fast path, which can significantly improve /// performance on some architectures. /// - Efficient handling of micro-contention using adaptive spinning. pub struct Once(AtomicU8); impl Once { /// Creates a new `Once` value. #[inline] pub const fn new() -> Once { Once(AtomicU8::new(0)) } } ``` -------------------------------- ### Get TypeId for Any Trait Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.Condvar Retrieves the `TypeId` of the current instance (`self`), which can be used for dynamic type checking and casting when working with trait objects. ```APIDOC Any::type_id(&self) -> TypeId ``` -------------------------------- ### Get RwLock Reference from ArcRwLockReadGuard Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.ArcRwLockReadGuard Returns a reference to the underlying `RwLock` instance, which is contained within an `Arc`. This method allows access to the `RwLock` itself from an `ArcRwLockReadGuard`. ```Rust pub fn rwlock(s: &ArcRwLockReadGuard) -> &Arc> ``` -------------------------------- ### ParkToken Struct API Reference Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.ParkToken Comprehensive API documentation for the `ParkToken` struct within the `parking_lot_core` crate. It details the struct's tuple fields and lists all explicitly implemented, auto-implemented, and blanket traits. ```APIDOC Struct ParkToken Description: A value associated with a parked thread which can be used by `unpark_filter`. Tuple Fields: - 0: usize Trait Implementations: - Clone - Copy - Debug - Eq - PartialEq - StructuralPartialEq Auto Trait Implementations: - Freeze - RefUnwindSafe - Send - Sync - Unpin - UnwindSafe Blanket Implementations: - Any - Borrow - BorrowMut - CloneToUninit - From - Into - ToOwned - TryFrom - TryInto ``` -------------------------------- ### Implement CloneToUninit for T (Blanket Implementation) Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/enum.ParkResult Documents the blanket implementation of the `CloneToUninit` trait for any type `T` that implements `Clone`. This is a nightly-only experimental API for performing copy-assignment to uninitialized memory. Includes the `clone_to_uninit` method. ```Rust impl CloneToUninit for T where T: Clone, unsafe fn clone_to_uninit(&self, dest: *mut u8) Performs copy-assignment from self to dest. ``` -------------------------------- ### Get TypeId for Any Trait in Rust Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.ArcRwLockWriteGuard Documents the `type_id` method of the `Any` trait. This method returns the `TypeId` of the `self` instance, which can be used for runtime type identification and comparison. ```APIDOC fn type_id(&self) -> TypeId ``` -------------------------------- ### Get Default Condvar Instance Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.Condvar Returns the default value for the `Condvar` type, typically used for initialization. This method is part of the `Default` trait implementation for `Condvar`. ```APIDOC Condvar::default() -> Condvar ``` -------------------------------- ### Implement CloneToUninit for T: Perform Copy-Assignment Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.ParkToken Provides a blanket implementation of the `CloneToUninit` trait for any type `T` that implements `Clone`. This experimental API performs copy-assignment from `self` to an uninitialized destination. ```APIDOC impl CloneToUninit for T where T: Clone unsafe fn clone_to_uninit(&self, dest: *mut u8) Parameters: dest: *mut u8 - The raw pointer to the uninitialized destination memory. Description: Performs copy-assignment from self to dest. This is a nightly-only experimental API. ``` -------------------------------- ### Rust BorrowMut Trait Implementation for T Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.RawRwLock Documents the `BorrowMut` trait implementation for any type `T`, allowing mutable borrowing of an owned value. This implementation provides a way to get a mutable reference to the underlying data. ```APIDOC impl BorrowMut for T where T: ?Sized fn borrow_mut(&mut self) -> &mut T Mutably borrows from an owned value. ``` -------------------------------- ### Implement Any Trait for Generic Type T Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.UnparkToken Details the blanket implementation of the `Any` trait for any type `T` that is `'static` and potentially unsized. This trait allows for downcasting to concrete types and provides a method to get the `TypeId` of `self`. ```APIDOC impl Any for T where T: 'static + ?Sized, fn type_id(&self) -> TypeId ``` -------------------------------- ### Rust: Run a Single Parking Test Scenario Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/src/parking_lot_core/parking_lot.rs The `run_parking_test` function sets up and executes a parking test based on the provided parameters. It initializes a `SingleLatchTest` for each latch and then spawns a specified number of threads. The full implementation would involve managing thread parking and unparking based on the test configuration. ```Rust fn run_parking_test( num_latches: usize, delay: Duration, num_threads: usize, num_single_unparks: usize, ) { let mut tests = Vec::with_capacity(num_latches); for _ in 0..num_latches { let test = Arc::new(SingleLatchTest::new(num_threads)); let mut threads = Vec::with_capacity(num_threads); for _ in 0..num_threads { let test = test.clone(); ``` -------------------------------- ### Rust parking_lot_core Crate `lib.rs` Structure and Public API Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/src/parking_lot_core/lib.rs This code snippet displays the `lib.rs` file of the `parking_lot_core` crate. It includes licensing, crate-level documentation explaining the 'parking lot' concept, conditional compilation flags for features like SGX and WASM atomics, internal module declarations, and public re-exports of key functions and types. These re-exports define the crate's public interface, exposing functionalities such as `park`, `unpark_one`, `SpinWait`, and various `ParkToken` and `UnparkResult` enums. ```Rust // Copyright 2016 Amanieu d'Antras // // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. //! This library exposes a low-level API for creating your own efficient //! synchronization primitives. //! //! # The parking lot //! //! To keep synchronization primitives small, all thread queuing and suspending //! functionality is offloaded to the *parking lot*. The idea behind this is based //! on the Webkit [`WTF::ParkingLot`](https://webkit.org/blog/6161/locking-in-webkit/) //! class, which essentially consists of a hash table mapping of lock addresses //! to queues of parked (sleeping) threads. The Webkit parking lot was itself //! inspired by Linux [futexes](http://man7.org/linux/man-pages/man2/futex.2.html), //! but it is more powerful since it allows invoking callbacks while holding a //! queue lock. //! //! There are two main operations that can be performed on the parking lot: //! //! - *Parking* refers to suspending the thread while simultaneously enqueuing it //! on a queue keyed by some address. //! - *Unparking* refers to dequeuing a thread from a queue keyed by some address //! and resuming it. //! //! See the documentation of the individual functions for more details. //! //! # Building custom synchronization primitives //! //! Building custom synchronization primitives is very simple since the parking //! lot takes care of all the hard parts for you. A simple example for a //! custom primitive would be to integrate a `Mutex` inside another data type. //! Since a mutex only requires 2 bits, it can share space with other data. //! For example, one could create an `ArcMutex` type that combines the atomic //! reference count and the two mutex bits in the same atomic word. #![warn(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr( all(target_env = "sgx", target_vendor = "fortanix"), feature(sgx_platform) )] #![cfg_attr( all( feature = "nightly", target_family = "wasm", target_feature = "atomics" ), feature(stdarch_wasm_atomic_wait) )] mod parking_lot; mod spinwait; mod thread_parker; mod util; mod word_lock; pub use self::parking_lot::deadlock; pub use self::parking_lot::{park, unpark_all, unpark_filter, unpark_one, unpark_requeue}; pub use self::parking_lot::{ FilterOp, ParkResult, ParkToken, RequeueOp, UnparkResult, UnparkToken, }; pub use self::parking_lot::{DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; pub use self::spinwait::SpinWait; ``` -------------------------------- ### Get Semaphore Memory Address in Rust Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/src/parking_lot_core/parking_lot.rs A utility function that returns the memory address of the semaphore as a `usize`. This address is crucial for low-level parking and unparking operations, serving as a unique identifier for the wait queue associated with the semaphore. ```Rust fn semaphore_addr(&self) -> usize { &self.semaphore as *const _ as usize } ``` -------------------------------- ### API Documentation: parking_lot_core Functions Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/index Core functions for parking, unparking, and requeueing threads within the parking_lot_core synchronization primitives. ```APIDOC park: Parks the current thread in the queue associated with the given key. unpark_all: Unparks all threads in the queue associated with the given key. unpark_filter: Unparks a number of threads from the front of the queue associated with `key` depending on the results of a filter function which inspects the `ParkToken` associated with each thread. unpark_one: Unparks one thread from the queue associated with the given key. unpark_requeue: Removes all threads from the queue associated with `key_from`, optionally unparks the first one and requeues the rest onto the queue associated with `key_to`. ``` -------------------------------- ### Rust: Basic RwLock Read, Write, and Upgradable Read Operations Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/rwlock.rs This test demonstrates the fundamental usage of `RwLock` by acquiring and dropping read, write, and upgradable read guards. It verifies that basic locking mechanisms work as expected without contention. ```Rust let l = RwLock::new(()); drop(l.read()); drop(l.write()); drop(l.upgradable_read()); drop((l.read(), l.read())); drop((l.read(), l.upgradable_read())); drop(l.write()); ``` -------------------------------- ### Basic Usage of parking_lot::RwLock Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/type.RwLock Demonstrates how to create a new `RwLock`, acquire multiple read locks concurrently, and acquire an exclusive write lock to modify the protected data. Shows the behavior of read and write guards and their automatic release. ```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 ``` -------------------------------- ### Rust: Notifying a Single Thread with Condvar::notify_one Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.Condvar This example demonstrates the usage of `Condvar::notify_one()` to wake up a single waiting thread. It also shows how to check the boolean return value to determine if any thread was actually woken up. ```Rust use parking_lot::Condvar; let condvar = Condvar::new(); // do something with condvar, share it with other threads if !condvar.notify_one() { println!("Nobody was listening for this."); } ``` -------------------------------- ### parking_lot Crate API Item Listing Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/all Lists all public structs, enums, functions, and type aliases available in the `parking_lot` crate, providing an overview of its concurrency primitives. ```APIDOC Struct: ArcMutexGuard ``` ```APIDOC Struct: ArcReentrantMutexGuard ``` ```APIDOC Struct: ArcRwLockReadGuard ``` ```APIDOC Struct: ArcRwLockUpgradableReadGuard ``` ```APIDOC Struct: ArcRwLockWriteGuard ``` ```APIDOC Struct: Condvar ``` ```APIDOC Struct: Once ``` ```APIDOC Struct: RawFairMutex ``` ```APIDOC Struct: RawMutex ``` ```APIDOC Struct: RawRwLock ``` ```APIDOC Struct: RawThreadId ``` ```APIDOC Struct: WaitTimeoutResult ``` ```APIDOC Enum: OnceState ``` ```APIDOC Function: const_fair_mutex ``` ```APIDOC Function: const_mutex ``` ```APIDOC Function: const_reentrant_mutex ``` ```APIDOC Function: const_rwlock ``` ```APIDOC Function: deadlock::check_deadlock ``` ```APIDOC Type Alias: FairMutex ``` ```APIDOC Type Alias: FairMutexGuard ``` ```APIDOC Type Alias: MappedFairMutexGuard ``` ```APIDOC Type Alias: MappedMutexGuard ``` ```APIDOC Type Alias: MappedReentrantMutexGuard ``` ```APIDOC Type Alias: MappedRwLockReadGuard ``` ```APIDOC Type Alias: MappedRwLockWriteGuard ``` ```APIDOC Type Alias: Mutex ``` ```APIDOC Type Alias: MutexGuard ``` ```APIDOC Type Alias: ReentrantMutex ``` ```APIDOC Type Alias: ReentrantMutexGuard ``` ```APIDOC Type Alias: RwLock ``` ```APIDOC Type Alias: RwLockReadGuard ``` ```APIDOC Type Alias: RwLockUpgradableReadGuard ``` ```APIDOC Type Alias: RwLockWriteGuard ``` -------------------------------- ### Define AtomicElisionExt Trait for Lock Elision Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/elision.rs This trait extends atomic types with methods for hardware lock elision. It defines `elision_compare_exchange_acquire` to start a transaction and `elision_fetch_sub_release` to end one, providing an interface for optimized atomic operations. ```Rust pub trait AtomicElisionExt { type IntType; // Perform a compare_exchange and start a transaction fn elision_compare_exchange_acquire( &self, current: Self::IntType, new: Self::IntType, ) -> Result; // Perform a fetch_sub and end a transaction fn elision_fetch_sub_release(&self, val: Self::IntType) -> Self::IntType; } ``` -------------------------------- ### parking_lot::RwLock API Documentation Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/rwlock.rs Comprehensive API documentation for the `parking_lot::RwLock` type, its associated functions, and RAII guard structures. It details the lock's behavior, fairness guarantees, and distinctions from the standard library `RwLock`. ```APIDOC RwLock: Description: A reader-writer lock that allows multiple readers or at most one writer at any time. The write portion provides exclusive access for modification, while the read portion allows shared, read-only access. It employs a task-fair locking policy to prevent both reader and writer starvation. Recursive acquisition of a read lock within a single thread may lead to a deadlock. The type parameter `T` must satisfy `Send` for cross-thread sharing and `Sync` for concurrent access via readers. RAII guards returned by locking methods implement `Deref` (and `DerefMut` for write methods) for access to the protected data. Fairness: - Uses eventual fairness (e.g., fair unlock every 0.5ms on average) to balance throughput and fairness, ensuring the lock eventually goes to waiting threads. - Critical sections longer than 1ms always trigger a fair unlock. - Fair unlock can be explicitly forced by calling `RwLockReadGuard::unlock_fair` or `RwLockWriteGuard::unlock_fair`. Differences from standard library `RwLock`: - Supports atomically downgrading a write lock to a read lock. - Implements a task-fair locking policy. - No poisoning: the lock is released normally on panic. - Requires only 1 word of space, avoiding boxing. - Can be statically constructed. - Does not require any drop glue. - Features an inline fast path for uncontended cases. - Efficiently handles micro-contention using adaptive spinning. - Allows raw locking and unlocking without a guard. - Supports eventual fairness. - Provides optional fair unlock methods (`unlock_fair`). const_rwlock(val: T) -> RwLock: Description: Creates a new unlocked `RwLock` instance. This function enables `RwLock` creation in a constant context on stable Rust. Parameters: - val: T - The initial value to be protected by the `RwLock`. Returns: - RwLock - A new, unlocked `RwLock` instance. RwLockReadGuard<'a, T>: Description: An RAII structure responsible for releasing the shared read access of a lock when it is dropped. RwLockWriteGuard<'a, T>: Description: An RAII structure responsible for releasing the exclusive write access of a lock when it is dropped. MappedRwLockReadGuard: Description: An RAII read lock guard returned by `RwLockReadGuard::map`. This guard can point to a subfield of the protected data, differing from `RwLockReadGuard` by allowing access to a specific part of the locked data. ``` -------------------------------- ### Basic Usage of parking_lot::RwLock in Rust Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/rwlock.rs This example demonstrates how to acquire and release read and write locks using `parking_lot::RwLock`. It shows that multiple read locks can be held concurrently, while only one write lock can be held at a time, ensuring exclusive access for modifications. ```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 ``` -------------------------------- ### Fairly Unlock RwLock from ArcRwLockReadGuard Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.ArcRwLockReadGuard Unlocks the `RwLock` using a fair unlock protocol, ensuring that waiting threads get a chance to acquire the lock in a fair manner. This method is available when the raw lock implements `RawRwLockFair` and is functionally identical to `RwLockReadGuard::unlock_fair`. ```Rust pub fn unlock_fair(s: ArcRwLockReadGuard) ``` -------------------------------- ### ParkToken: Implement Clone Trait Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.ParkToken Provides methods for cloning `ParkToken` instances, including deep copy and copy-assignment functionality. ```APIDOC fn clone(&self) -> ParkToken self: The instance to clone. returns: A new ParkToken instance, a copy of the original. ``` ```APIDOC fn clone_from(&mut self, source: &Self) self: The instance to be modified. source: The ParkToken instance to copy from. returns: None. Performs copy-assignment in place. ``` -------------------------------- ### Rust ReentrantMutex Serialization and Deserialization with Serde Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/remutex.rs This example illustrates how to serialize and deserialize a `ReentrantMutex` instance using the `serde` feature. It demonstrates creating a mutex with some content, converting it into a byte array, then reconstructing the mutex from those bytes, and finally asserting that the original and deserialized contents are identical. ```Rust let contents: Vec = vec![0, 1, 2]; let mutex = ReentrantMutex::new(contents.clone()); let serialized = serialize(&mutex).unwrap(); let deserialized: ReentrantMutex> = deserialize(&serialized).unwrap(); assert_eq!(*(mutex.lock()), *(deserialized.lock())); assert_eq!(contents, *(deserialized.lock())); ``` -------------------------------- ### UnparkToken Struct API Reference Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.UnparkToken API documentation for the `UnparkToken` struct within the `parking_lot_core` crate. It details its tuple fields and lists all implemented traits, including standard Rust traits like `Clone`, `Copy`, `Debug`, `Eq`, `PartialEq`, and various auto and blanket implementations. ```APIDOC Struct UnparkToken Description: A value which is passed from an unparker to a parked thread. Tuple Fields: 0: usize Trait Implementations: - Clone - Copy - Debug - Eq - PartialEq - StructuralPartialEq Auto Trait Implementations: - Freeze - RefUnwindSafe - Send - Sync - Unpin - UnwindSafe Blanket Implementations: - Any - Borrow - BorrowMut - CloneToUninit - From - Into - ToOwned - TryFrom - TryInto ``` -------------------------------- ### Rust parking_lot_core Functions API Reference Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/all Lists the public functions available in the `parking_lot_core` crate, including those for deadlock management and parking/unparking threads. ```APIDOC Functions: deadlock::acquire_resource deadlock::release_resource park unpark_all unpark_filter unpark_one unpark_requeue ``` -------------------------------- ### Rust BorrowMut Trait: Mutably Borrowing Values Source: https://docs.rs/parking_lot/latest/parking_lot/_core/0.9.11/x86_64-unknown-linux-gnu/parking_lot_core/struct.SpinWait Documents the `BorrowMut` trait and its `borrow_mut` method, which allows mutable borrowing from an owned value. This is part of Rust's core `borrow` module, providing a way to get a mutable reference to the contained value. ```APIDOC fn borrow_mut(&mut self) -> &mut T Description: Mutably borrows from an owned value. ``` -------------------------------- ### Get ReentrantMutex Reference from ArcReentrantMutexGuard (RawMutex) Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.ArcReentrantMutexGuard Returns a reference to the `ReentrantMutex` that this `ArcReentrantMutexGuard` object is guarding, specifically the `Arc`-contained instance. This method is available when `R` implements `RawMutex`, `G` implements `GetThreadId`, and `T` is `?Sized`. It provides direct access to the underlying mutex. ```APIDOC pub fn remutex(s: &ArcReentrantMutexGuard) -> &Arc> Parameters: s: &ArcReentrantMutexGuard - A reference to the ArcReentrantMutexGuard instance. Returns: &Arc> - A reference to the ReentrantMutex contained within its Arc. ``` -------------------------------- ### Rust Once::call_once_slow Internal Initialization Logic Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/once.rs This internal, non-generic, and `#[cold]` function implements the core logic for `Once` initialization. It handles thread synchronization using spin-waits and parking, checks for `DONE_BIT` and `POISON_BIT`, and attempts to acquire a lock to run the closure. It uses `compare_exchange_weak` for atomic state updates and `parking_lot_core::park` for thread parking. ```Rust #[cold] fn call_once_slow(&self, ignore_poison: bool, f: &mut dyn FnMut(OnceState)) { let mut spinwait = SpinWait::new(); let mut state = self.0.load(Ordering::Relaxed); loop { // If another thread called the closure, we're done if state & DONE_BIT != 0 { // An acquire fence is needed here since we didn't load the // state with Ordering::Acquire. fence(Ordering::Acquire); return; } // If the state has been poisoned and we aren't forcing, then panic if state & POISON_BIT != 0 && !ignore_poison { // Need the fence here as well for the same reason fence(Ordering::Acquire); panic!("Once instance has previously been poisoned"); } // Grab the lock if it isn't locked, even if there is a queue on it. // We also clear the poison bit since we are going to try running // the closure again. if state & LOCKED_BIT == 0 { match self.0.compare_exchange_weak( state, (state | LOCKED_BIT) & !POISON_BIT, Ordering::Acquire, Ordering::Relaxed, ) { Ok(_) => break, Err(x) => state = x, } continue; } // If there is no queue, try spinning a few times if state & PARKED_BIT == 0 && spinwait.spin() { state = self.0.load(Ordering::Relaxed); continue; } // Set the parked bit if state & PARKED_BIT == 0 { if let Err(x) = self.0.compare_exchange_weak( state, state | PARKED_BIT, Ordering::Relaxed, Ordering::Relaxed, ) { state = x; continue; } } // Park our thread until we are woken up by the thread that owns the // lock. let addr = self as *const _ as usize; let validate = || self.0.load(Ordering::Relaxed) == LOCKED_BIT | PARKED_BIT; let before_sleep = || {}; let timed_out = |_, _| unreachable!(); unsafe { parking_lot_core::park( addr, validate, before_sleep, timed_out, DEFAULT_PARK_TOKEN, None, ); } // Loop back and check if the done bit was set spinwait.reset(); } } ``` -------------------------------- ### APIDOC: parking_lot::Once Methods Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/parking_lot/struct.Once Details the public methods available for the `parking_lot::Once` struct. These methods allow for creating new `Once` instances, executing code exactly once, forcing re-execution, and querying the current state of the `Once` instance. ```APIDOC impl Once Source: ../src/parking_lot/once.rs.html#79-310 Methods: call_once call_once_force pub const fn new() -> Once Description: Creates a new `Once` value. Source: ../src/parking_lot/once.rs.html#82-84 pub fn state(&self) -> OnceState Description: Returns the current state of this `Once`. Source: ../src/parking_lot/once.rs.html#88-99 ``` -------------------------------- ### Rust: Test 1 Producer, 1 Consumer, 1 Slot Queue Source: https://docs.rs/parking_lot/latest/parking_lot/0.12.4/src/parking_lot/condvar.rs Tests a producer-consumer setup with a single producer, single consumer, and a queue size of one. It sends 10,000 messages per producer with 'NotifyStyle::All' and no timeout, simulating a highly contended single-slot queue. ```Rust one_producer_one_consumer_one_slot( num_producers: 1, num_consumers: 1, max_queue_size: 1, messages_per_producer: 10000, notification_style: NotifyStyle::All, timeout: Timeout::Forever, delay_seconds: 0 ); ```