use crate::loom::sync::atomic::AtomicBool; use std::cell::UnsafeCell; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::sync::atomic::Ordering::SeqCst; pub(crate) struct TryLock { locked: AtomicBool, data: UnsafeCell, } pub(crate) struct LockGuard<'a, T> { lock: &'a TryLock, _p: PhantomData>, } unsafe impl Send for TryLock {} unsafe impl Sync for TryLock {} unsafe impl Sync for LockGuard<'_, T> {} macro_rules! new { ($data:ident) => { TryLock { locked: AtomicBool::new(false), data: UnsafeCell::new($data), } }; } impl TryLock { #[cfg(not(loom))] /// Create a new `TryLock` pub(crate) const fn new(data: T) -> TryLock { new!(data) } #[cfg(loom)] /// Create a new `TryLock` pub(crate) fn new(data: T) -> TryLock { new!(data) } /// Attempt to acquire lock pub(crate) fn try_lock(&self) -> Option> { if self .locked .compare_exchange(false, true, SeqCst, SeqCst) .is_err() { return None; } Some(LockGuard { lock: self, _p: PhantomData, }) } } impl Deref for LockGuard<'_, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.lock.data.get() } } } impl DerefMut for LockGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.lock.data.get() } } } impl Drop for LockGuard<'_, T> { fn drop(&mut self) { self.lock.locked.store(false, SeqCst); } }