• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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