summaryrefslogtreecommitdiffstats
path: root/tokio/src/util/try_lock.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tokio/src/util/try_lock.rs')
-rw-r--r--tokio/src/util/try_lock.rs63
1 files changed, 63 insertions, 0 deletions
diff --git a/tokio/src/util/try_lock.rs b/tokio/src/util/try_lock.rs
new file mode 100644
index 00000000..493fce88
--- /dev/null
+++ b/tokio/src/util/try_lock.rs
@@ -0,0 +1,63 @@
+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> { }
+
+impl<T> TryLock<T> {
+ /// Create a new `TryLock`
+ pub(crate) fn new(data: T) -> TryLock<T> {
+ TryLock {
+ locked: AtomicBool::new(false),
+ data: UnsafeCell::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);
+ }
+}