1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! Provides simple spinlocks based on the abstractions provided by the [`lock_api`] crate.
//!
//! [`lock_api`]: https://docs.rs/lock_api/
//!
//! # Examples
//!
//! Use [`Spinlock`] for mutual exclusion:
//!
//! ```
//! use spinning_top::Spinlock;
//!
//! fn main() {
//!     let data = String::from("Hello");
//!     // Wrap some data in a spinlock
//!     let spinlock = Spinlock::new(data);
//!
//!     // Lock the spinlock to get a mutex guard for the data
//!     let mut locked_data = spinlock.lock();
//!     // The guard implements the `Deref` trait, so we can use it like a `&String`
//!     assert_eq!(locked_data.as_str(), "Hello");
//!     // It also implements `DerefMut` so mutation is possible too. This is safe
//!     // because the spinlock ensures mutual exclusion
//!     locked_data.make_ascii_uppercase();
//!     assert_eq!(locked_data.as_str(), "HELLO");
//!
//!     // the guard automatically frees the lock at the end of the scope
//! }
//! ```
//!
//! Use [`RwSpinlock`] if you need a readers-writer lock:
//!
//! ```
//! use spinning_top::RwSpinlock;
//!
//! let lock = RwSpinlock::new(5);
//!
//! // many reader locks can be held at once
//! {
//!     let r1 = lock.read();
//!     let r2 = lock.read();
//!     assert_eq!(*r1, 5);
//!     assert_eq!(*r2, 5);
//! } // read locks are dropped at this point
//!
//! // only one write lock may be held, however
//! {
//!     let mut w = lock.write();
//!     *w += 1;
//!     assert_eq!(*w, 6);
//! } // write lock is dropped here
//! ```

#![cfg_attr(not(test), no_std)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]

/// The spinlock implemenation is based on the abstractions provided by the `lock_api` crate.
pub use lock_api;

pub use rw_spinlock::{BackoffRwSpinlock, RawRwSpinlock, RwSpinlock};
pub use spinlock::{BackoffSpinlock, RawSpinlock, Spinlock};

/// Type aliases for guards.
pub mod guard {
    #[cfg(feature = "arc_lock")]
    pub use super::rw_spinlock::{
        ArcBackoffRwSpinlockReadGuard, ArcBackoffRwSpinlockUpgradableReadGuard,
        ArcBackoffRwSpinlockWriteGuard, ArcRwSpinlockReadGuard, ArcRwSpinlockUpgradableReadGuard,
        ArcRwSpinlockWriteGuard,
    };
    pub use super::rw_spinlock::{
        BackoffRwSpinlockReadGuard, BackoffRwSpinlockUpgradableReadGuard,
        BackoffRwSpinlockWriteGuard, RwSpinlockReadGuard, RwSpinlockUpgradableReadGuard,
        RwSpinlockWriteGuard,
    };
    #[cfg(feature = "arc_lock")]
    pub use super::spinlock::{ArcBackoffSpinlockGuard, ArcSpinlockGuard};
    pub use super::spinlock::{
        BackoffSpinlockGuard, MappedBackoffSpinlockGuard, MappedSpinlockGuard, SpinlockGuard,
    };
}

pub mod relax;
mod rw_spinlock;
mod spinlock;