1pub mod sync {
3 super::impl_bilock!(sync);
4
5 unsafe impl<T: Send> Send for Inner<T> {}
6 unsafe impl<T: Send> Sync for Inner<T> {}
7
8 impl<T: Send> crate::AssertMt for BiLock<T> {}
9 impl<T: Send> crate::AssertMt for BiLockAcquire<'_, T> {}
10 impl<T: Send> crate::AssertMt for BiLockGuard<'_, T> {}
11}
12
13pub mod unsync {
15 super::impl_bilock!(unsync);
16}
17
18macro_rules! impl_bilock {
19 ($sync:ident) => {
20 use std::{
21 cell::UnsafeCell,
22 fmt::Debug,
23 future::Future,
24 ops::{Deref, DerefMut},
25 pin::Pin,
26 task::{Context, Poll},
27 };
28
29 use crate::$sync::{flag::Flag, shared::Shared, waker_slot::WakerSlot};
30
31 pub struct BiLock<T>(Shared<Inner<T>>);
33
34 impl<T> Debug for BiLock<T>
35 where
36 T: Debug,
37 {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 f.debug_struct("BiLock")
40 .field("locked", &self.0.locked.get())
41 .finish()
42 }
43 }
44
45 impl<T> BiLock<T> {
46 pub fn new(data: T) -> (Self, Self) {
49 let inner = Shared::new(Inner {
50 data: UnsafeCell::new(data),
51 waiter: WakerSlot::new(),
52 locked: Flag::new(false),
53 });
54 (Self(inner.clone()), Self(inner))
55 }
56
57 pub fn lock(&self) -> BiLockAcquire<'_, T> {
59 BiLockAcquire { inner: &self.0 }
60 }
61
62 pub fn try_join(self, other: Self) -> Option<T> {
64 if Shared::ptr_eq(&self.0, &other.0) {
65 drop(other);
66 let value = Shared::try_unwrap(self.0)
67 .map_err(|_| ())
68 .expect("BiLock is still shared")
69 .data
70 .into_inner();
71 Some(value)
72 } else {
73 None
74 }
75 }
76
77 #[allow(unused)]
79 pub fn join(self, other: Self) -> T {
80 if let Some(value) = self.try_join(other) {
81 value
82 } else {
83 #[cold]
84 fn panic_unrelated() -> ! {
85 panic!("Unrelated `BiLock` passed to `BiLock::join`.")
86 }
87
88 panic_unrelated()
89 }
90 }
91 }
92
93 pub struct BiLockAcquire<'a, T> {
95 inner: &'a Inner<T>,
96 }
97
98 impl<'a, T> Future for BiLockAcquire<'a, T> {
99 type Output = BiLockGuard<'a, T>;
100
101 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
102 let this = self.get_mut();
103 if this.inner.locked.swap(true) {
104 this.inner.waiter.register(cx.waker());
105 Poll::Pending
106 } else {
107 Poll::Ready(BiLockGuard { inner: this.inner })
108 }
109 }
110 }
111
112 struct Inner<T: ?Sized> {
113 locked: Flag,
114 waiter: WakerSlot,
115 data: UnsafeCell<T>,
116 }
117
118 pub struct BiLockGuard<'a, T: ?Sized> {
120 inner: &'a Inner<T>,
121 }
122
123 impl<T: ?Sized> Deref for BiLockGuard<'_, T> {
124 type Target = T;
125
126 fn deref(&self) -> &Self::Target {
127 unsafe { &*self.inner.data.get() }
128 }
129 }
130
131 impl<T: ?Sized> DerefMut for BiLockGuard<'_, T> {
132 fn deref_mut(&mut self) -> &mut Self::Target {
133 unsafe { &mut *self.inner.data.get() }
134 }
135 }
136
137 impl<T: ?Sized> Drop for BiLockGuard<'_, T> {
138 fn drop(&mut self) {
139 self.inner.locked.swap(false);
140 self.inner.waiter.wake();
141 }
142 }
143 };
144}
145
146use impl_bilock;