1parking_lot 2============ 3 4[](https://github.com/Amanieu/parking_lot/actions) 5[](https://crates.io/crates/parking_lot) 6 7[Documentation (synchronization primitives)](https://docs.rs/parking_lot/) 8 9[Documentation (core parking lot API)](https://docs.rs/parking_lot_core/) 10 11[Documentation (type-safe lock API)](https://docs.rs/lock_api/) 12 13This library provides implementations of `Mutex`, `RwLock`, `Condvar` and 14`Once` that are smaller, faster and more flexible than those in the Rust 15standard library, as well as a `ReentrantMutex` type which supports recursive 16locking. It also exposes a low-level API for creating your own efficient 17synchronization primitives. 18 19When tested on x86_64 Linux, `parking_lot::Mutex` was found to be 1.5x 20faster than `std::sync::Mutex` when uncontended, and up to 5x faster when 21contended from multiple threads. The numbers for `RwLock` vary depending on 22the number of reader and writer threads, but are almost always faster than 23the standard library `RwLock`, and even up to 50x faster in some cases. 24 25## Features 26 27The primitives provided by this library have several advantages over those 28in the Rust standard library: 29 301. `Mutex` and `Once` only require 1 byte of storage space, while `Condvar` 31 and `RwLock` only require 1 word of storage space. On the other hand the 32 standard library primitives require a dynamically allocated `Box` to hold 33 OS-specific synchronization primitives. The small size of `Mutex` in 34 particular encourages the use of fine-grained locks to increase 35 parallelism. 362. Since they consist of just a single atomic variable, have constant 37 initializers and don't need destructors, these primitives can be used as 38 `static` global variables. The standard library primitives require 39 dynamic initialization and thus need to be lazily initialized with 40 `lazy_static!`. 413. Uncontended lock acquisition and release is done through fast inline 42 paths which only require a single atomic operation. 434. Microcontention (a contended lock with a short critical section) is 44 efficiently handled by spinning a few times while trying to acquire a 45 lock. 465. The locks are adaptive and will suspend a thread after a few failed spin 47 attempts. This makes the locks suitable for both long and short critical 48 sections. 496. `Condvar`, `RwLock` and `Once` work on Windows XP, unlike the standard 50 library versions of those types. 517. `RwLock` takes advantage of hardware lock elision on processors that 52 support it, which can lead to huge performance wins with many readers. 53 This must be enabled with the `hardware-lock-elision` feature. 548. `RwLock` uses a task-fair locking policy, which avoids reader and writer 55 starvation, whereas the standard library version makes no guarantees. 569. `Condvar` is guaranteed not to produce spurious wakeups. A thread will 57 only be woken up if it timed out or it was woken up by a notification. 5810. `Condvar::notify_all` will only wake up a single thread and requeue the 59 rest to wait on the associated `Mutex`. This avoids a thundering herd 60 problem where all threads try to acquire the lock at the same time. 6111. `RwLock` supports atomically downgrading a write lock into a read lock. 6212. `Mutex` and `RwLock` allow raw unlocking without a RAII guard object. 6313. `Mutex<()>` and `RwLock<()>` allow raw locking without a RAII guard 64 object. 6514. `Mutex` and `RwLock` support [eventual fairness](https://trac.webkit.org/changeset/203350) 66 which allows them to be fair on average without sacrificing performance. 6715. A `ReentrantMutex` type which supports recursive locking. 6816. An *experimental* deadlock detector that works for `Mutex`, 69 `RwLock` and `ReentrantMutex`. This feature is disabled by default and 70 can be enabled via the `deadlock_detection` feature. 7117. `RwLock` supports atomically upgrading an "upgradable" read lock into a 72 write lock. 7318. Optional support for [serde](https://docs.serde.rs/serde/). Enable via the 74 feature `serde`. **NOTE!** this support is for `Mutex`, `ReentrantMutex`, 75 and `RwLock` only; `Condvar` and `Once` are not currently supported. 7619. Lock guards can be sent to other threads when the `send_guard` feature is 77 enabled. 78 79## The parking lot 80 81To keep these primitives small, all thread queuing and suspending 82functionality is offloaded to the *parking lot*. The idea behind this is 83based on the Webkit [`WTF::ParkingLot`](https://webkit.org/blog/6161/locking-in-webkit/) 84class, which essentially consists of a hash table mapping of lock addresses 85to queues of parked (sleeping) threads. The Webkit parking lot was itself 86inspired by Linux [futexes](https://man7.org/linux/man-pages/man2/futex.2.html), 87but it is more powerful since it allows invoking callbacks while holding a queue 88lock. 89 90## Nightly vs stable 91 92There are a few restrictions when using this library on stable Rust: 93 94- The `wasm32-unknown-unknown` target is only fully supported on nightly with 95 `-C target-feature=+atomics` in `RUSTFLAGS` and `-Z build-std` passed to cargo. 96 parking_lot will work mostly fine on stable, the only difference is it will 97 panic instead of block forever if you hit a deadlock. 98 Just make sure not to enable `-C target-feature=+atomics` on stable as that 99 will allow wasm to run with multiple threads which will completely break 100 parking_lot's concurrency guarantees. 101 102To enable nightly-only functionality, you need to enable the `nightly` feature 103in Cargo (see below). 104 105## Usage 106 107Add this to your `Cargo.toml`: 108 109```toml 110[dependencies] 111parking_lot = "0.12" 112``` 113 114To enable nightly-only features, add this to your `Cargo.toml` instead: 115 116```toml 117[dependencies] 118parking_lot = { version = "0.12", features = ["nightly"] } 119``` 120 121The experimental deadlock detector can be enabled with the 122`deadlock_detection` Cargo feature. 123 124To allow sending `MutexGuard`s and `RwLock*Guard`s to other threads, enable the 125`send_guard` option. 126 127Note that the `deadlock_detection` and `send_guard` features are incompatible 128and cannot be used together. 129 130Hardware lock elision support for x86 can be enabled with the 131`hardware-lock-elision` feature. This requires Rust 1.59 due to the use of 132inline assembly. 133 134The core parking lot API is provided by the `parking_lot_core` crate. It is 135separate from the synchronization primitives in the `parking_lot` crate so that 136changes to the core API do not cause breaking changes for users of `parking_lot`. 137 138## Minimum Rust version 139 140The current minimum required Rust version is 1.49. Any change to this is 141considered a breaking change and will require a major version bump. 142 143## License 144 145Licensed under either of 146 147 * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) 148 * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) 149 150at your option. 151 152### Contribution 153 154Unless you explicitly state otherwise, any contribution intentionally submitted 155for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 156additional terms or conditions. 157