#![no_std]
use core::cell::UnsafeCell;
use core::fmt::{Debug, Display};
use core::sync::atomic::{AtomicBool, Ordering};
pub struct AtomicLock<T> {
lock: AtomicBool,
data: UnsafeCell<T>,
}
impl<T> AtomicLock<T> {
pub const fn new(data: T) -> Self {
AtomicLock {
lock: AtomicBool::new(false),
data: UnsafeCell::new(data),
}
}
pub fn lock(&self) -> Option<Guard<T>> {
match self.lock.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed) {
Ok(_) => Some(
Guard {
lock: self,
data: unsafe { &mut *self.data.get() },
}
),
Err(_) => None,
}
}
pub fn unlock(&self) {
let old = self.lock.swap(false, Ordering::Release);
assert_eq!(old, true);
}
pub unsafe fn data(&self) -> &mut T {
&mut *self.data.get()
}
pub fn into_inner(self) -> T {
self.data.into_inner()
}
}
impl<T: Debug> Debug for AtomicLock<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let guard = self.lock();
match guard {
None => {
f.debug_struct("AtomicLock")
.field("locked", &true)
.field("data", &"<Locked>")
.finish()
}
Some(data) => {
f.debug_struct("AtomicLock")
.field("locked", &false)
.field("data", &data)
.finish()
}
}
}
}
#[derive(Debug)]
#[must_use]
pub struct Guard<'a, T> {
lock: &'a AtomicLock<T>,
data: &'a mut T,
}
impl<'a, T> Drop for Guard<'a, T> {
fn drop(&mut self) {
self.lock.unlock();
}
}
impl <T> Default for AtomicLock<T> where T: Default {
fn default() -> Self {
AtomicLock::new(T::default())
}
}
impl <T> From<T> for AtomicLock<T> {
fn from(data: T) -> Self {
AtomicLock::new(data)
}
}
unsafe impl<T> Send for AtomicLock<T> {}
unsafe impl<T> Sync for AtomicLock<T> {}
impl <'a, T> Display for Guard<'a, T> where T: Display {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.data.fmt(f)
}
}
impl <'a, T> AsRef<T> for Guard<'a, T> {
fn as_ref(&self) -> &T {
self.data
}
}
impl <'a, T> AsMut<T> for Guard<'a, T> {
fn as_mut(&mut self) -> &mut T {
self.data
}
}
impl <'a, T> core::ops::Deref for Guard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data
}
}
impl <'a, T> core::ops::DerefMut for Guard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.data
}
}
unsafe impl<'a, T> Send for Guard<'a, T> {}