]>
Commit | Line | Data |
---|---|---|
b7449926 XL |
1 | // Copyright 2018 Amanieu d'Antras |
2 | // | |
3 | // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or | |
4 | // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or | |
5 | // http://opensource.org/licenses/MIT>, at your option. This file may not be | |
6 | // copied, modified, or distributed except according to those terms. | |
7 | ||
8 | //! This library provides type-safe and fully-featured `Mutex` and `RwLock` | |
9 | //! types which wrap a simple raw mutex or rwlock type. This has several | |
10 | //! benefits: not only does it eliminate a large portion of the work in | |
11 | //! implementing custom lock types, it also allows users to write code which is | |
12 | //! generic with regards to different lock implementations. | |
13 | //! | |
e1599b0c | 14 | //! Basic usage of this crate is very straightforward: |
b7449926 XL |
15 | //! |
16 | //! 1. Create a raw lock type. This should only contain the lock state, not any | |
17 | //! data protected by the lock. | |
18 | //! 2. Implement the `RawMutex` trait for your custom lock type. | |
19 | //! 3. Export your mutex as a type alias for `lock_api::Mutex`, and | |
20 | //! your mutex guard as a type alias for `lock_api::MutexGuard`. | |
21 | //! See the [example](#example) below for details. | |
22 | //! | |
23 | //! This process is similar for RwLocks, except that two guards need to be | |
24 | //! exported instead of one. (Or 3 guards if your type supports upgradable read | |
25 | //! locks, see [extension traits](#extension-traits) below for details) | |
26 | //! | |
27 | //! # Example | |
28 | //! | |
29 | //! ``` | |
e1599b0c XL |
30 | //! use lock_api::{RawMutex, Mutex, GuardSend}; |
31 | //! use std::sync::atomic::{AtomicBool, Ordering}; | |
b7449926 XL |
32 | //! |
33 | //! // 1. Define our raw lock type | |
34 | //! pub struct RawSpinlock(AtomicBool); | |
35 | //! | |
36 | //! // 2. Implement RawMutex for this type | |
37 | //! unsafe impl RawMutex for RawSpinlock { | |
e1599b0c XL |
38 | //! const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false)); |
39 | //! | |
40 | //! // A spinlock guard can be sent to another thread and unlocked there | |
41 | //! type GuardMarker = GuardSend; | |
b7449926 XL |
42 | //! |
43 | //! fn lock(&self) { | |
44 | //! // Note: This isn't the best way of implementing a spinlock, but it | |
45 | //! // suffices for the sake of this example. | |
46 | //! while !self.try_lock() {} | |
47 | //! } | |
48 | //! | |
49 | //! fn try_lock(&self) -> bool { | |
ba9703b0 XL |
50 | //! self.0 |
51 | //! .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) | |
52 | //! .is_ok() | |
b7449926 XL |
53 | //! } |
54 | //! | |
55 | //! fn unlock(&self) { | |
56 | //! self.0.store(false, Ordering::Release); | |
57 | //! } | |
58 | //! } | |
59 | //! | |
60 | //! // 3. Export the wrappers. This are the types that your users will actually use. | |
61 | //! pub type Spinlock<T> = lock_api::Mutex<RawSpinlock, T>; | |
62 | //! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>; | |
63 | //! ``` | |
64 | //! | |
65 | //! # Extension traits | |
66 | //! | |
67 | //! In addition to basic locking & unlocking functionality, you have the option | |
68 | //! of exposing additional functionality in your lock types by implementing | |
69 | //! additional traits for it. Examples of extension features include: | |
70 | //! | |
71 | //! - Fair unlocking (`RawMutexFair`, `RawRwLockFair`) | |
72 | //! - Lock timeouts (`RawMutexTimed`, `RawRwLockTimed`) | |
73 | //! - Downgradable write locks (`RawRwLockDowngradable`) | |
74 | //! - Recursive read locks (`RawRwLockRecursive`) | |
75 | //! - Upgradable read locks (`RawRwLockUpgrade`) | |
76 | //! | |
77 | //! The `Mutex` and `RwLock` wrappers will automatically expose this additional | |
78 | //! functionality if the raw lock type implements these extension traits. | |
79 | //! | |
80 | //! # Cargo features | |
81 | //! | |
82 | //! This crate supports two cargo features: | |
83 | //! | |
84 | //! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate. | |
85 | //! - `nightly`: Enables nightly-only features. At the moment the only such | |
86 | //! feature is `const fn` constructors for lock types. | |
87 | ||
88 | #![no_std] | |
89 | #![warn(missing_docs)] | |
e1599b0c | 90 | #![warn(rust_2018_idioms)] |
b7449926 XL |
91 | #![cfg_attr(feature = "nightly", feature(const_fn))] |
92 | ||
93 | #[macro_use] | |
94 | extern crate scopeguard; | |
95 | ||
b7449926 XL |
96 | /// Marker type which indicates that the Guard type for a lock is `Send`. |
97 | pub struct GuardSend(()); | |
98 | ||
99 | /// Marker type which indicates that the Guard type for a lock is not `Send`. | |
100 | pub struct GuardNoSend(*mut ()); | |
101 | ||
102 | mod mutex; | |
e1599b0c | 103 | pub use crate::mutex::*; |
b7449926 XL |
104 | |
105 | mod remutex; | |
e1599b0c | 106 | pub use crate::remutex::*; |
b7449926 XL |
107 | |
108 | mod rwlock; | |
e1599b0c | 109 | pub use crate::rwlock::*; |