option_lock/lib.rs
1//! This crate defines a locking structure wrapping an `Option` value. The lock
2//! can be acquired using a single atomic operation. The `OptionLock` structure
3//! is represented as one atomic `u8` variable along with the current value of
4//! the lock (which may be empty). It can be constructed in `const` contexts.
5//!
6//! The `try_lock` and `try_take` operations are non-blocking and appropriate
7//! for using within a polled `Future`, but the lock cannot register wakers or
8//! automatically park the current thread. A traditional `Mutex` or the
9//! `async-lock` crate may be used in this case.
10//!
11//! This structure allows for multiple usage patterns. A basic example (in this
12//! case an AtomicI32 could be substituted):
13//!
14//! ```
15//! use option_lock::{OptionLock, OptionGuard};
16//!
17//! static SHARED: OptionLock<i32> = OptionLock::new(0);
18//!
19//! fn try_increase() -> bool {
20//! if let Ok(mut guard) = SHARED.try_lock() {
21//! let next = guard.take().unwrap() + 1;
22//! OptionGuard::replace(&mut guard, next);
23//! true
24//! } else {
25//! false
26//! }
27//! }
28//! ```
29//!
30//! There are additional examples in the code repository.
31//!
32//! This crate uses `unsafe` code blocks. It is `no_std`-compatible when compiled
33//! without the `std` feature.
34
35#![cfg_attr(not(feature = "std"), no_std)]
36#![cfg_attr(docsrs, feature(doc_cfg))]
37#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
38
39#[cfg(any(test, feature = "alloc"))]
40extern crate alloc;
41
42mod error;
43pub use self::error::OptionLockError;
44
45mod lock;
46
47pub use self::lock::{OptionGuard, OptionLock};
48
49#[cfg(feature = "alloc")]
50mod arc;
51#[cfg(feature = "alloc")]
52pub use self::arc::{MutexGuardArc, OptionGuardArc};
53
54mod once;
55pub use self::once::{Lazy, OnceCell};
56
57mod mutex;
58pub use self::mutex::{Mutex, MutexGuard};