flaque 0.2.0

A fast, concurrent, lock-free, and sometimes wait-free, pool implementation
Documentation
// Copyright 2026 Ivan Enderlin <ivan@mnt.io>. Licensed under the EUPL, version
// 1.2. See the `LICENSE` file.

use std::{
    cell::UnsafeCell,
    marker::PhantomData,
    ops::{Deref, DerefMut},
    sync::atomic::{AtomicBool, Ordering},
};

/// A lock guarded by an `AtomicBool`.
///
/// It mimics the [`try_lock`] crate. The difference is the lock guard has a
/// “read” or “write” mode, adding a bit more safety regarding a misuse of the
/// API.
///
/// [`try_lock`]: https://crates.io/crates/try-lock
pub struct TryLock<T> {
    is_locked: AtomicBool,
    value: UnsafeCell<T>,
}

impl<T> TryLock<T> {
    #[inline]
    pub const fn new(value: T) -> TryLock<T> {
        TryLock {
            is_locked: AtomicBool::new(false),
            value: UnsafeCell::new(value),
        }
    }

    /// Try to acquire an exclusive access to the value. The guard only
    /// implements [`Deref`].
    #[inline]
    pub fn try_read_lock(&self) -> Option<TryLockGuard<'_, T, Read>> {
        self.try_lock()
    }

    /// Try to acquire an exclusive access to the value. The guard implements
    /// [`Deref`] and [`DerefMut`].
    #[inline]
    pub fn try_write_lock(&self) -> Option<TryLockGuard<'_, T, Write>> {
        self.try_lock()
    }

    #[inline]
    fn try_lock<K>(&self) -> Option<TryLockGuard<'_, T, K>> {
        if !self.is_locked.swap(true, Ordering::Acquire) {
            Some(TryLockGuard { lock: self, _phantom: PhantomData })
        } else {
            None
        }
    }
}

pub struct Read;
pub struct Write;

pub struct TryLockGuard<'lock, T: 'lock, K> {
    lock: &'lock TryLock<T>,
    _phantom: PhantomData<(*mut T, K)>,
}

// Release the lock.
impl<'lock, T, K> Drop for TryLockGuard<'lock, T, K> {
    fn drop(&mut self) {
        self.lock.is_locked.store(false, Ordering::Release);
    }
}

// `Deref` is implemented on all `TryLockGuard`.
impl<'lock, T, K> Deref for TryLockGuard<'lock, T, K> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { &*self.lock.value.get() }
    }
}

// `DerefMut` is implemented only for `TryLockGuard` with `Write`.
impl<'lock, T> DerefMut for TryLockGuard<'lock, T, Write> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *self.lock.value.get() }
    }
}