|
|
||
|---|---|---|
| .. | ||
| .github/workflows | ||
| src | ||
| tests | ||
| .cargo_vcs_info.json | ||
| Android.bp | ||
| CHANGELOG.md | ||
| Cargo.toml | ||
| Cargo.toml.orig | ||
| LICENSE | ||
| LICENSE-APACHE | ||
| LICENSE-MIT | ||
| METADATA | ||
| MODULE_LICENSE_APACHE2 | ||
| OWNERS | ||
| README.md | ||
| TEST_MAPPING | ||
| bors.toml | ||
| cargo2android.json | ||
README.md
parking_lot
Documentation (synchronization primitives)
Documentation (core parking lot API)
Documentation (type-safe lock API)
This library provides implementations of Mutex, RwLock, Condvar and
Once that are smaller, faster and more flexible than those in the Rust
standard library, as well as a ReentrantMutex type which supports recursive
locking. It also exposes a low-level API for creating your own efficient
synchronization primitives.
When tested on x86_64 Linux, parking_lot::Mutex was found to be 1.5x
faster than std::sync::Mutex when uncontended, and up to 5x faster when
contended from multiple threads. The numbers for RwLock vary depending on
the number of reader and writer threads, but are almost always faster than
the standard library RwLock, and even up to 50x faster in some cases.
Features
The primitives provided by this library have several advantages over those in the Rust standard library:
MutexandOnceonly require 1 byte of storage space, whileCondvarandRwLockonly require 1 word of storage space. On the other hand the standard library primitives require a dynamically allocatedBoxto hold OS-specific synchronization primitives. The small size ofMutexin particular encourages the use of fine-grained locks to increase parallelism.- Since they consist of just a single atomic variable, have constant
initializers and don't need destructors, these primitives can be used as
staticglobal variables. The standard library primitives require dynamic initialization and thus need to be lazily initialized withlazy_static!. - Uncontended lock acquisition and release is done through fast inline paths which only require a single atomic operation.
- Microcontention (a contended lock with a short critical section) is efficiently handled by spinning a few times while trying to acquire a lock.
- The locks are adaptive and will suspend a thread after a few failed spin attempts. This makes the locks suitable for both long and short critical sections.
Condvar,RwLockandOncework on Windows XP, unlike the standard library versions of those types.RwLocktakes advantage of hardware lock elision on processors that support it, which can lead to huge performance wins with many readers. This must be enabled with thehardware-lock-elisionfeature.RwLockuses a task-fair locking policy, which avoids reader and writer starvation, whereas the standard library version makes no guarantees.Condvaris guaranteed not to produce spurious wakeups. A thread will only be woken up if it timed out or it was woken up by a notification.Condvar::notify_allwill only wake up a single thread and requeue the rest to wait on the associatedMutex. This avoids a thundering herd problem where all threads try to acquire the lock at the same time.RwLocksupports atomically downgrading a write lock into a read lock.MutexandRwLockallow raw unlocking without a RAII guard object.Mutex<()>andRwLock<()>allow raw locking without a RAII guard object.MutexandRwLocksupport eventual fairness which allows them to be fair on average without sacrificing performance.- A
ReentrantMutextype which supports recursive locking. - An experimental deadlock detector that works for
Mutex,RwLockandReentrantMutex. This feature is disabled by default and can be enabled via thedeadlock_detectionfeature. RwLocksupports atomically upgrading an "upgradable" read lock into a write lock.- Optional support for serde. Enable via the
feature
serde. NOTE! this support is forMutex,ReentrantMutex, andRwLockonly;CondvarandOnceare not currently supported. - Lock guards can be sent to other threads when the
send_guardfeature is enabled.
The parking lot
To keep these 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
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,
but it is more powerful since it allows invoking callbacks while holding a queue
lock.
Nightly vs stable
There are a few restrictions when using this library on stable Rust:
- You will have to use the
const_*functions (e.g.const_mutex(val)) to statically initialize the locking primitives. Using e.g.Mutex::new(val)does not work on stable Rust yet. - The
wasm32-unknown-unknowntarget is only supported on nightly and requires-C target-feature=+atomicsinRUSTFLAGS.
To enable nightly-only functionality, you need to enable the nightly feature
in Cargo (see below).
Usage
Add this to your Cargo.toml:
[dependencies]
parking_lot = "0.11"
To enable nightly-only features, add this to your Cargo.toml instead:
[dependencies]
parking_lot = { version = "0.11", features = ["nightly"] }
The experimental deadlock detector can be enabled with the
deadlock_detection Cargo feature.
To allow sending MutexGuards and RwLock*Guards to other threads, enable the
send_guard option.
Note that the deadlock_detection and send_guard features are incompatible
and cannot be used together.
Hardware lock elision support for x86 can be enabled with the
hardware-lock-elision feature. This requires Rust 1.59 due to the use of
inline assembly.
The core parking lot API is provided by the parking_lot_core crate. It is
separate from the synchronization primitives in the parking_lot crate so that
changes to the core API do not cause breaking changes for users of parking_lot.
Minimum Rust version
The current minimum required Rust version is 1.49. Any change to this is considered a breaking change and will require a major version bump.
License
Licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.