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 //! 14 //! Basic usage of this crate is very straightforward: 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 //! ``` 30 //! use lock_api::{RawMutex, Mutex, GuardSend}; 31 //! use std::sync::atomic::{AtomicBool, Ordering}; 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 { 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; 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 { 50 //! self.0 51 //! .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) 52 //! .is_ok() 53 //! } 54 //! 55 //! unsafe 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)] 90 #![warn(rust_2018_idioms)] 91 #![cfg_attr(feature = "nightly", feature(const_fn))] 92 93 #[macro_use] 94 extern crate scopeguard; 95 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 unsafe impl Sync for GuardNoSend {} 103 104 mod mutex; 105 pub use crate::mutex::*; 106 107 mod remutex; 108 pub use crate::remutex::*; 109 110 mod rwlock; 111 pub use crate::rwlock::*; 112