1 #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] 2 #![deny(missing_docs)] 3 4 //! This crate provides [spin-based](https://en.wikipedia.org/wiki/Spinlock) versions of the 5 //! primitives in `std::sync` and `std::lazy`. Because synchronization is done through spinning, 6 //! the primitives are suitable for use in `no_std` environments. 7 //! 8 //! # Features 9 //! 10 //! - `Mutex`, `RwLock`, `Once`/`SyncOnceCell`, and `SyncLazy` equivalents 11 //! 12 //! - Support for `no_std` environments 13 //! 14 //! - [`lock_api`](https://crates.io/crates/lock_api) compatibility 15 //! 16 //! - Upgradeable `RwLock` guards 17 //! 18 //! - Guards can be sent and shared between threads 19 //! 20 //! - Guard leaking 21 //! 22 //! # Relationship with `std::sync` 23 //! 24 //! While `spin` is not a drop-in replacement for `std::sync` (and 25 //! [should not be considered as such](https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html)) 26 //! an effort is made to keep this crate reasonably consistent with `std::sync`. 27 //! 28 //! Many of the types defined in this crate have 'additional capabilities' when compared to `std::sync`: 29 //! 30 //! - Because spinning does not depend on the thread-driven model of `std::sync`, guards ([`MutexGuard`], 31 //! [`RwLockReadGuard`], [`RwLockWriteGuard`], etc.) may be sent and shared between threads. 32 //! 33 //! - [`RwLockUpgradableGuard`] supports being upgrades into a [`RwLockWriteGuard`]. 34 //! 35 //! - Guards support [leaking](https://doc.rust-lang.org/nomicon/leaking.html). 36 //! 37 //! - [`Once`] owns the value returned by its `call_once` initializer. 38 //! 39 //! - [`RwLock`] supports counting readers and writers. 40 //! 41 //! Conversely, the types in this crate do not have some of the features `std::sync` has: 42 //! 43 //! - Locks do not track [panic poisoning](https://doc.rust-lang.org/nomicon/poisoning.html). 44 //! 45 //! ## Feature flags 46 //! 47 //! The crate comes with a few feature flags that you may wish to use. 48 //! 49 //! - `lock_api` enabled support for [`lock_api`](https://crates.io/crates/lock_api) 50 //! 51 //! - `ticket_mutex` uses a ticket lock for the implementation of `Mutex` 52 //! 53 //! - `std` enables support for thread yielding instead of spinning 54 55 #[cfg(any(test, feature = "std"))] 56 extern crate core; 57 58 // Choose a different relaxation strategy based on whether `std` is available or not. 59 #[cfg(not(feature = "std"))] 60 use core::sync::atomic::spin_loop_hint as relax; 61 #[cfg(feature = "std")] 62 use std::thread::yield_now as relax; 63 64 pub mod barrier; 65 pub mod lazy; 66 pub mod mutex; 67 pub mod once; 68 pub mod rw_lock; 69 70 pub use barrier::Barrier; 71 pub use lazy::Lazy; 72 pub use mutex::{Mutex, MutexGuard}; 73 pub use once::Once; 74 pub use rw_lock::{RwLock, RwLockReadGuard, RwLockWriteGuard, RwLockUpgradableGuard}; 75 76 /// Spin synchronisation primitives, but compatible with [`lock_api`](https://crates.io/crates/lock_api). 77 #[cfg(feature = "lock_api1")] 78 pub mod lock_api { 79 /// A lock that provides mutually exclusive data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). 80 pub type Mutex<T> = lock_api::Mutex<crate::Mutex<()>, T>; 81 82 /// A guard that provides mutable data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). 83 pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, crate::Mutex<()>, T>; 84 85 /// A lock that provides data access to either one writer or many readers (compatible with [`lock_api`](https://crates.io/crates/lock_api)). 86 pub type RwLock<T> = lock_api::RwLock<crate::RwLock<()>, T>; 87 88 /// A guard that provides immutable data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). 89 pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, crate::RwLock<()>, T>; 90 91 /// A guard that provides mutable data access (compatible with [`lock_api`](https://crates.io/crates/lock_api)). 92 pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, crate::RwLock<()>, T>; 93 94 /// A guard that provides immutable data access but can be upgraded to [`RwLockWriteGuard`] (compatible with [`lock_api`](https://crates.io/crates/lock_api)). 95 pub type RwLockUpgradableReadGuard<'a, T> = 96 lock_api::RwLockUpgradableReadGuard<'a, crate::RwLock<()>, T>; 97 } 98