lelet_simple_lock/
lib.rs

1#![no_std]
2
3use core::cell::UnsafeCell;
4use core::fmt;
5use core::marker::PhantomData;
6use core::ops::Deref;
7use core::ops::DerefMut;
8use core::sync::atomic::AtomicBool;
9use core::sync::atomic::Ordering;
10
11/// A simple lock.
12///
13/// Intentionally to not providing the `lock`, you can spin loop `try_lock` if you want.
14/// You should use [`Mutex`] if you need blocking lock.
15///
16/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
17pub struct SimpleLock<T: ?Sized> {
18    locked: AtomicBool,
19    value: UnsafeCell<T>,
20}
21
22unsafe impl<T: ?Sized + Send> Send for SimpleLock<T> {}
23unsafe impl<T: ?Sized + Send> Sync for SimpleLock<T> {}
24
25impl<T> SimpleLock<T> {
26    /// Returns a new SimpleLock initialized with `value`.
27    pub fn new(value: T) -> SimpleLock<T> {
28        SimpleLock {
29            locked: AtomicBool::new(false),
30            value: UnsafeCell::new(value),
31        }
32    }
33}
34
35impl<T: ?Sized + Default> Default for SimpleLock<T> {
36    fn default() -> SimpleLock<T> {
37        SimpleLock::new(T::default())
38    }
39}
40
41impl<T: ?Sized> SimpleLock<T> {
42    /// Try to lock.
43    pub fn try_lock(&self) -> Option<SimpleLockGuard<T>> {
44        if self.locked.swap(true, Ordering::Acquire) {
45            None
46        } else {
47            Some(SimpleLockGuard {
48                parent: self,
49                _marker: PhantomData,
50            })
51        }
52    }
53
54    /// Is locked ?
55    pub fn is_locked(&self) -> bool {
56        self.locked.load(Ordering::Relaxed)
57    }
58}
59
60impl<T> From<T> for SimpleLock<T> {
61    fn from(t: T) -> Self {
62        SimpleLock::new(t)
63    }
64}
65
66impl<T: ?Sized + fmt::Debug> fmt::Debug for SimpleLock<T> {
67    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68        match self.try_lock() {
69            Some(guard) => f.debug_tuple("SimpleLock").field(&&*guard).finish(),
70            None => f.write_str("SimpleLock(<locked>)"),
71        }
72    }
73}
74
75/// A guard holding a [`SimpleLock`].
76///
77/// [`SimpleLock`]: struct.SimpleLock.html
78pub struct SimpleLockGuard<'a, T: 'a + ?Sized> {
79    parent: &'a SimpleLock<T>,
80
81    // !Send + !Sync
82    _marker: PhantomData<*mut ()>,
83}
84
85unsafe impl<T: ?Sized + Sync> Sync for SimpleLockGuard<'_, T> {}
86
87impl<T: ?Sized> Drop for SimpleLockGuard<'_, T> {
88    fn drop(&mut self) {
89        self.parent.locked.store(false, Ordering::Release);
90    }
91}
92
93impl<T: ?Sized> Deref for SimpleLockGuard<'_, T> {
94    type Target = T;
95
96    fn deref(&self) -> &Self::Target {
97        unsafe { &*self.parent.value.get() }
98    }
99}
100
101impl<T: ?Sized> DerefMut for SimpleLockGuard<'_, T> {
102    fn deref_mut(&mut self) -> &mut Self::Target {
103        unsafe { &mut *self.parent.value.get() }
104    }
105}
106
107impl<T: ?Sized + fmt::Debug> fmt::Debug for SimpleLockGuard<'_, T> {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        fmt::Debug::fmt(&**self, f)
110    }
111}
112
113impl<T: ?Sized + fmt::Display> fmt::Display for SimpleLockGuard<'_, T> {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        (**self).fmt(f)
116    }
117}