README.md
1parking_lot
2============
3
4![Rust](https://github.com/Amanieu/parking_lot/workflows/Rust/badge.svg)
5[![Crates.io](https://img.shields.io/crates/v/parking_lot.svg)](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.
538. `RwLock` uses a task-fair locking policy, which avoids reader and writer
54 starvation, whereas the standard library version makes no guarantees.
559. `Condvar` is guaranteed not to produce spurious wakeups. A thread will
56 only be woken up if it timed out or it was woken up by a notification.
5710. `Condvar::notify_all` will only wake up a single thread and requeue the
58 rest to wait on the associated `Mutex`. This avoids a thundering herd
59 problem where all threads try to acquire the lock at the same time.
6011. `RwLock` supports atomically downgrading a write lock into a read lock.
6112. `Mutex` and `RwLock` allow raw unlocking without a RAII guard object.
6213. `Mutex<()>` and `RwLock<()>` allow raw locking without a RAII guard
63 object.
6414. `Mutex` and `RwLock` support [eventual fairness](https://trac.webkit.org/changeset/203350)
65 which allows them to be fair on average without sacrificing performance.
6615. A `ReentrantMutex` type which supports recursive locking.
6716. An *experimental* deadlock detector that works for `Mutex`,
68 `RwLock` and `ReentrantMutex`. This feature is disabled by default and
69 can be enabled via the `deadlock_detection` feature.
7017. `RwLock` supports atomically upgrading an "upgradable" read lock into a
71 write lock.
7218. Optional support for [serde](https://docs.serde.rs/serde/). Enable via the
73 feature `serde`. **NOTE!** this support is for `Mutex`, `ReentrantMutex`,
74 and `RwLock` only; `Condvar` and `Once` are not currently supported.
7519. Lock guards can be sent to other threads when the `send_guard` feature is
76 enabled.
77
78## The parking lot
79
80To keep these primitives small, all thread queuing and suspending
81functionality is offloaded to the *parking lot*. The idea behind this is
82based on the Webkit [`WTF::ParkingLot`](https://webkit.org/blog/6161/locking-in-webkit/)
83class, which essentially consists of a hash table mapping of lock addresses
84to queues of parked (sleeping) threads. The Webkit parking lot was itself
85inspired by Linux [futexes](http://man7.org/linux/man-pages/man2/futex.2.html),
86but it is more powerful since it allows invoking callbacks while holding a queue
87lock.
88
89## Nightly vs stable
90
91There are a few restrictions when using this library on stable Rust:
92
93- You will have to use the `const_*` functions (e.g. `const_mutex(val)`) to
94 statically initialize the locking primitives. Using e.g. `Mutex::new(val)`
95 does not work on stable Rust yet.
96- `RwLock` will not be able to take advantage of hardware lock elision for
97 readers, which improves performance when there are multiple readers.
98- The `wasm32-unknown-unknown` target is only supported on nightly and requires
99 `-C target-feature=+atomics` in `RUSTFLAGS`.
100
101To enable nightly-only functionality, you need to enable the `nightly` feature
102in Cargo (see below).
103
104## Usage
105
106Add this to your `Cargo.toml`:
107
108```toml
109[dependencies]
110parking_lot = "0.11"
111```
112
113To enable nightly-only features, add this to your `Cargo.toml` instead:
114
115```toml
116[dependencies]
117parking_lot = { version = "0.11", features = ["nightly"] }
118```
119
120The experimental deadlock detector can be enabled with the
121`deadlock_detection` Cargo feature.
122
123To allow sending `MutexGuard`s and `RwLock*Guard`s to other threads, enable the
124`send_guard` option.
125
126Note that the `deadlock_detection` and `send_guard` features are incompatible
127and cannot be used together.
128
129The core parking lot API is provided by the `parking_lot_core` crate. It is
130separate from the synchronization primitives in the `parking_lot` crate so that
131changes to the core API do not cause breaking changes for users of `parking_lot`.
132
133## Minimum Rust version
134
135The current minimum required Rust version is 1.36. Any change to this is
136considered a breaking change and will require a major version bump.
137
138## License
139
140Licensed under either of
141
142 * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
143 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
144
145at your option.
146
147### Contribution
148
149Unless you explicitly state otherwise, any contribution intentionally submitted
150for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
151additional terms or conditions.
152