1 use crate::loom::sync::atomic::AtomicBool;
2 
3 use std::cell::UnsafeCell;
4 use std::marker::PhantomData;
5 use std::ops::{Deref, DerefMut};
6 use std::sync::atomic::Ordering::SeqCst;
7 
8 pub(crate) struct TryLock<T> {
9     locked: AtomicBool,
10     data: UnsafeCell<T>,
11 }
12 
13 pub(crate) struct LockGuard<'a, T> {
14     lock: &'a TryLock<T>,
15     _p: PhantomData<std::rc::Rc<()>>,
16 }
17 
18 unsafe impl<T: Send> Send for TryLock<T> {}
19 unsafe impl<T: Send> Sync for TryLock<T> {}
20 
21 unsafe impl<T: Sync> Sync for LockGuard<'_, T> {}
22 
23 macro_rules! new {
24     ($data:ident) => {
25         TryLock {
26             locked: AtomicBool::new(false),
27             data: UnsafeCell::new($data),
28         }
29     };
30 }
31 
32 impl<T> TryLock<T> {
33     #[cfg(not(loom))]
34     /// Create a new `TryLock`
new(data: T) -> TryLock<T>35     pub(crate) const fn new(data: T) -> TryLock<T> {
36         new!(data)
37     }
38 
39     #[cfg(loom)]
40     /// Create a new `TryLock`
new(data: T) -> TryLock<T>41     pub(crate) fn new(data: T) -> TryLock<T> {
42         new!(data)
43     }
44 
45     /// Attempt to acquire lock
try_lock(&self) -> Option<LockGuard<'_, T>>46     pub(crate) fn try_lock(&self) -> Option<LockGuard<'_, T>> {
47         if self
48             .locked
49             .compare_exchange(false, true, SeqCst, SeqCst)
50             .is_err()
51         {
52             return None;
53         }
54 
55         Some(LockGuard {
56             lock: self,
57             _p: PhantomData,
58         })
59     }
60 }
61 
62 impl<T> Deref for LockGuard<'_, T> {
63     type Target = T;
64 
deref(&self) -> &T65     fn deref(&self) -> &T {
66         unsafe { &*self.lock.data.get() }
67     }
68 }
69 
70 impl<T> DerefMut for LockGuard<'_, T> {
deref_mut(&mut self) -> &mut T71     fn deref_mut(&mut self) -> &mut T {
72         unsafe { &mut *self.lock.data.get() }
73     }
74 }
75 
76 impl<T> Drop for LockGuard<'_, T> {
drop(&mut self)77     fn drop(&mut self) {
78         self.lock.locked.store(false, SeqCst);
79     }
80 }
81