safe-lock 0.1.4

A lock struct with a `const fn` constructor and no `unsafe` - ARCHIVED
Documentation
//! # ARCHIVED ARCHIVED ARCHIVED
//! This crate is archived and will not be updated.
//!
//! [`std::sync::Mutex`] got a `const` constructor, making this crate unnecessary.
//! See [rustlang/rust#66806](https://github.com/rust-lang/rust/issues/66806).
//! Don't use this crate.  Just use [`std::sync::Mutex`].
//!
//! For folks who continue using this crate,
//! `SafeLock` is now a simple wrapper around [`std::sync::Mutex`],
//! so their tests will run a bit faster.
//!
//! ----
//!
//! # safe-lock
//!
//! A simple `SafeLock` struct.
//!
//! # Use Cases
//! - Run tests sequentially
//! - Prevent concurrent operations on atomic values
//! - Prevent concurrent operations on data and systems outside the Rust runtime
//!
//! # Features
//! - Const constructor
//! - Depends only on `std`
//! - `forbid(unsafe_code)`
//! - 100% test coverage
//!
//! # Limitations
//! - Not a `Mutex<T>`.  Does not contain a value.
//! - Unoptimized.  Uses
//!   [`AtomicBool`](https://doc.rust-lang.org/core/sync/atomic/struct.AtomicBool.html)
//!   in a spinlock, not fast OS locks.
//! - Not a fair lock.  If multiple threads acquire the lock in loops,
//!   some may never acquire it.
//!
//! # Alternatives
//! - [`rusty-fork`](https://crates.io/crates/rusty-fork)
//!   - Run tests in separate processes
//! - [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)
//!   - Part of the Rust standard library: well reviewed, well tested, and well maintained.
//!   - Uses fast OS locks
//!   - Has no const constructor.  See [rust#66806](https://github.com/rust-lang/rust/issues/66806)
//!     and [const-eval#3](https://github.com/rust-lang/const-eval/issues/3).
//!     You can work around this with unstable
//!     [`core::lazy::OnceCell`](https://doc.rust-lang.org/core/lazy/struct.OnceCell.html)
//!     or various `unsafe` crates:
//!     [`lazy_static`](https://crates.io/crates/lazy_static),
//!     [`once_cell`](https://crates.io/crates/once_cell),
//!     [`lazycell`](https://crates.io/crates/lazycell), and
//!     [`conquer-once`](https://crates.io/crates/conquer-once).
//! - [`parking_lot`](https://crates.io/crates/parking_lot)
//!   - Well written code.
//!     Many hope that it will end up in the Rust standard library someday.
//!   - Contains plenty of `unsafe`
//! - [`try-lock`](https://crates.io/crates/try-lock)
//!   - Popular
//!   - No dependencies, `no_std`
//!   - Uses `unsafe`
//! - [`ruspiro-lock`](https://crates.io/crates/ruspiro-lock)
//!   - Sync and async locks
//!   - No dependencies, `no_std`
//!   - Uses `unsafe`
//! - [`flexible-locks`](https://crates.io/crates/flexible-locks)
//!   - Lots of `unsafe`
//!   - Uses fast OS locks
//!   - Unmaintained
//!
//! # Related Crates
//! - [`safina-sync`](https://crates.io/crates/safina-sync)
//!   provides a safe async `Mutex`
//!
//! # Example
//!
//! Make some tests run sequentially so they don't interfere with each other:
//! ```unknown
//! use safe_lock::SafeLock;
//! static LOCK: SafeLock = SafeLock::new();
//!
//! [#test]
//! fn test1() {
//!     let _guard = LOCK.lock();
//!     // ...
//! }
//!
//! [#test]
//! fn test2() {
//!     let _guard = LOCK.lock();
//!     // ...
//! }
//! ```
//!
//! # Cargo Geiger Safety Report
//! # Changelog
//! - v0.1.4
//!    - Make `SafeLock` a wrapper around [`std::sync::Mutex`] since it got a const constructor.
//!    - Add archival notice.
//! - v0.1.3 - Increase test coverage
//! - v0.1.2 - Use `Acquire` and `Release` ordering
//! - v0.1.1 - Update docs
//! - v0.1.0 - Initial version
#![forbid(unsafe_code)]
use std::sync::{Mutex, MutexGuard, PoisonError};

/// A handle to the acquired lock.  Drop this to release the lock.
#[allow(dead_code)]
pub struct SafeLockGuard<'x>(MutexGuard<'x, ()>);

/// A lock.
///
/// See [`lock`](#method.lock).
///
/// This is not a fair lock.
/// If multiple threads acquire the lock in loops,
/// some may never acquire it.
///
/// # Example
///
/// Make some tests run sequentially so they don't interfere with each other:
/// ```unknown
/// use safe_lock::SafeLock;
/// static LOCK: SafeLock = SafeLock::new();
///
/// [#test]
/// fn test1() {
///     let _guard = LOCK.lock();
///     // ...
/// }
///
/// [#test]
/// fn test2() {
///     let _guard = LOCK.lock();
///     // ...
/// }
/// ```
pub struct SafeLock(Mutex<()>);
impl SafeLock {
    #[must_use]
    pub const fn new() -> SafeLock {
        SafeLock(Mutex::new(()))
    }

    /// Waits until the lock is free, then acquires the lock.
    ///
    /// Multiple threads can call `lock` but only one will acquire the lock
    /// and return.
    ///
    /// Drop the returned `SafeLockGuard` to release the lock.
    ///
    /// This is not a fair lock.
    /// If multiple threads acquire the lock in loops,
    /// some may never acquire it.
    #[must_use]
    pub fn lock(&self) -> Option<SafeLockGuard> {
        let guard = self.0.lock().unwrap_or_else(PoisonError::into_inner);
        Some(SafeLockGuard(guard))
    }
}
impl Default for SafeLock {
    fn default() -> Self {
        Self::new()
    }
}