diff options
Diffstat (limited to 'third_party/rust/tokio/src/util/try_lock.rs')
-rw-r--r-- | third_party/rust/tokio/src/util/try_lock.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/third_party/rust/tokio/src/util/try_lock.rs b/third_party/rust/tokio/src/util/try_lock.rs new file mode 100644 index 0000000000..8b0edb4a87 --- /dev/null +++ b/third_party/rust/tokio/src/util/try_lock.rs @@ -0,0 +1,80 @@ +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<T> { + locked: AtomicBool, + data: UnsafeCell<T>, +} + +pub(crate) struct LockGuard<'a, T> { + lock: &'a TryLock<T>, + _p: PhantomData<std::rc::Rc<()>>, +} + +unsafe impl<T: Send> Send for TryLock<T> {} +unsafe impl<T: Send> Sync for TryLock<T> {} + +unsafe impl<T: Sync> Sync for LockGuard<'_, T> {} + +macro_rules! new { + ($data:ident) => { + TryLock { + locked: AtomicBool::new(false), + data: UnsafeCell::new($data), + } + }; +} + +impl<T> TryLock<T> { + #[cfg(not(loom))] + /// Create a new `TryLock` + pub(crate) const fn new(data: T) -> TryLock<T> { + new!(data) + } + + #[cfg(loom)] + /// Create a new `TryLock` + pub(crate) fn new(data: T) -> TryLock<T> { + new!(data) + } + + /// Attempt to acquire lock + pub(crate) fn try_lock(&self) -> Option<LockGuard<'_, T>> { + if self + .locked + .compare_exchange(false, true, SeqCst, SeqCst) + .is_err() + { + return None; + } + + Some(LockGuard { + lock: self, + _p: PhantomData, + }) + } +} + +impl<T> Deref for LockGuard<'_, T> { + type Target = T; + + fn deref(&self) -> &T { + unsafe { &*self.lock.data.get() } + } +} + +impl<T> DerefMut for LockGuard<'_, T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.lock.data.get() } + } +} + +impl<T> Drop for LockGuard<'_, T> { + fn drop(&mut self) { + self.lock.locked.store(false, SeqCst); + } +} |