9
9
![ No_std] [ no_std-badge ]
10
10
11
11
MCS lock is a List-Based Queuing Lock that avoids network contention by having
12
- threads spin on local memory locations. The main properties of this mechanism are:
12
+ threads spin and/or park on local memory locations. The main properties of this
13
+ mechanism are:
13
14
14
15
- guarantees FIFO ordering of lock acquisitions;
15
16
- spins on locally-accessible flag variables only;
@@ -24,9 +25,10 @@ paper. And a simpler correctness proof of the MCS lock was proposed by
24
25
## Spinlock use cases
25
26
26
27
It is noteworthy to mention that [ spinlocks are usually not what you want] . The
27
- majority of use cases are well covered by OS-based mutexes like [ ` std::sync::Mutex ` ]
28
- and [ ` parking_lot::Mutex ` ] . These implementations will notify the system that the
29
- waiting thread should be parked, freeing the processor to work on something else.
28
+ majority of use cases are well covered by OS-based mutexes like
29
+ [ ` std::sync::Mutex ` ] or [ ` parking_lot::Mutex ` ] or even this crate's [ ` parking ` ]
30
+ Mutexes. These implementations will notify the system that the waiting thread
31
+ should be parked, freeing the processor to work on something else.
30
32
31
33
Spinlocks are only efficient in very few circumstances where the overhead
32
34
of context switching or process rescheduling are greater than busy waiting
@@ -160,6 +162,42 @@ fn main() {
160
162
}
161
163
```
162
164
165
+ ## Locking with thread parking MCS locks
166
+
167
+ This crate also supports MCS lock implementations that will put the blocking
168
+ threads to sleep. All ` no_std ` flavors: ` raw ` , ` barging ` have matching ` Mutex `
169
+ types under the [ ` parking ` ] module, with corresponding paths and public APIs,
170
+ that are thread parking capable. These implementations are not ` no_std `
171
+ compatible. See [ ` parking ` ] module for more information.
172
+
173
+ ``` rust
174
+ use std :: sync :: Arc ;
175
+ use std :: thread;
176
+
177
+ // Requires `parking` feature.
178
+ // Spins for a while then parks during contention.
179
+ use mcslock :: parking :: raw :: {spins :: Mutex , MutexNode };
180
+
181
+ // Requires `parking` and `thread_local` features.
182
+ mcslock :: thread_local_parking_node! (static NODE );
183
+
184
+ fn main () {
185
+ let mutex = Arc :: new (Mutex :: new (0 ));
186
+ let c_mutex = Arc :: clone (& mutex );
187
+
188
+ thread :: spawn (move || {
189
+ // Local node handles are provided by reference.
190
+ // Critical section must be defined as a closure.
191
+ c_mutex . lock_with_local_then (& NODE , | data | * data = 10 );
192
+ })
193
+ . join (). expect (" thread::spawn failed" );
194
+
195
+ // A node may also be transparently allocated in the stack.
196
+ // Critical section must be defined as a closure.
197
+ assert_eq! (mutex . try_lock_then (| data | * data . unwrap ()), 10 );
198
+ }
199
+ ```
200
+
163
201
## Features
164
202
165
203
This crate dos not provide any default features. Features that can be enabled
@@ -178,26 +216,36 @@ just simply busy-waits. This feature is not `no_std` compatible.
178
216
179
217
### thread_local
180
218
181
- The ` thread_local ` feature enables [ ` raw::Mutex ` ] locking APIs that operate over
182
- queue nodes that are stored at the thread local storage. These locking APIs
183
- require a static reference to [ ` raw::LocalMutexNode ` ] keys. Keys must be generated
184
- by the [ ` thread_local_node! ` ] macro. This feature also enables memory optimizations
185
- for [ ` barging::Mutex ` ] and locking operations. This feature is not ` no_std `
219
+ The ` thread_local ` feature enables [ ` raw::Mutex ` ] and [ ` parking::raw::Mutex ` ]
220
+ locking APIs that operate over queue nodes that are stored at the thread local
221
+ storage. These locking APIs require a static reference to [ ` raw::LocalMutexNode ` ]
222
+ and [ ` parking::raw::LocalMutexNode ` ] keys respectively. Keys must be generated
223
+ by the [ ` thread_local_node! ` ] and [ ` thread_local_parking_node! ` ] macros. This
224
+ feature also enables memory optimizations for [ ` barging::Mutex ` ] and
225
+ [ ` parking::barging::Mutex ` ] locking operations. This feature is not ` no_std `
186
226
compatible.
187
227
188
228
### barging
189
229
190
- The ` barging ` feature provides locking APIs that are compatible with the
191
- [ lock_api ] crate. It does not require node allocations from the caller.
192
- The [ ` barging ` ] module is suitable for ` no_std ` environments. This implementation
193
- is not fair (does not guarantee FIFO), but can improve throughput when the lock
194
- is heavily contended.
230
+ The ` barging ` feature provides locking APIs that are compatible with the [ lock_api ]
231
+ crate. It does not require node allocations from the caller. The [ ` barging ` ] module
232
+ is suitable for ` no_std ` environments, but [ ` parking::barging ` ] is not . This
233
+ implementation is not fair (does not guarantee FIFO), but can improve throughput
234
+ when the lock is heavily contended.
195
235
196
236
### lock_api
197
237
198
238
This feature implements the [ ` RawMutex ` ] trait from the [ lock_api] crate for
199
- [ ` barging::Mutex ` ] . Aliases are provided by the [ ` barging::lock_api ` ] (` no_std ` )
200
- module.
239
+ both [ ` barging::Mutex ` ] and [ ` parking::barging::Mutex ` ] . Aliases are provided by
240
+ the [ ` barging::lock_api ` ] (` no_std ` ) and [ ` parking::barging::lock_api ` ] modules.
241
+
242
+ ### parking
243
+
244
+ The ` parking ` feature provides Mutex implementations that are capable of putting
245
+ blocking threads waiting for the lock to sleep. These implementations are
246
+ published under the [ ` parking ` ] module. Each ` no_std ` mutex flavors provided
247
+ by this crate have corresponding parking implementations under that module.
248
+ Users may select a out of the box parking policy at [ ` parking::park ` ] .
201
249
202
250
## Minimum Supported Rust Version (MSRV)
203
251
@@ -258,10 +306,18 @@ each of your dependencies, including this one.
258
306
[ `raw::Mutex` ] : https://docs.rs/mcslock/latest/mcslock/raw/struct.Mutex.html
259
307
[ `raw::MutexNode` ] : https://docs.rs/mcslock/latest/mcslock/raw/struct.MutexNode.html
260
308
[ `raw::LocalMutexNode` ] : https://docs.rs/mcslock/latest/mcslock/raw/struct.LocalMutexNode.html
309
+ [ `parking` ] : https://docs.rs/mcslock/latest/mcslock/parking/index.html
310
+ [ `parking::park` ] : https://docs.rs/mcslock/latest/mcslock/parking/park/index.html
311
+ [ `parking::barging` ] : https://docs.rs/mcslock/latest/mcslock/parking/barging/index.html
312
+ [ `parking::lock_api` ] : https://docs.rs/mcslock/latest/mcslock/parking/lock_api/index.html
313
+ [ `parking::raw::Mutex` ] : https://docs.rs/mcslock/latest/mcslock/parking/raw/struct.Mutex.html
314
+ [ `parking::raw::LocalMutexNode` ] : https://docs.rs/mcslock/latest/mcslock/parking/raw/struct.LocalMutexNode.html
315
+ [ `parking::barging::Mutex` ] : https://docs.rs/mcslock/latest/mcslock/parking/barging/struct.Mutex.html
261
316
[ `barging` ] : https://docs.rs/mcslock/latest/mcslock/barging/index.html
262
317
[ `barging::lock_api` ] : https://docs.rs/mcslock/latest/mcslock/barging/lock_api/index.html
263
318
[ `barging::Mutex` ] : https://docs.rs/mcslock/latest/mcslock/barging/struct.Mutex.html
264
319
[ `thread_local_node!` ] : https://docs.rs/mcslock/latest/mcslock/macro.thread_local_node.html
320
+ [ `thread_local_parking_node!` ] : https://docs.rs/mcslock/latest/mcslock/macro.thread_local_parking_node.html
265
321
266
322
[ `std::sync::Mutex` ] : https://doc.rust-lang.org/std/sync/struct.Mutex.html
267
323
[ `std::thread::yield_now` ] : https://doc.rust-lang.org/std/thread/fn.yield_now.html
0 commit comments