dtact_util/sync/
rwlock.rs1use super::wait_queue::WaitQueue;
4use std::cell::UnsafeCell;
5use std::ops::{Deref, DerefMut};
6use std::sync::atomic::{AtomicIsize, Ordering};
7use std::task::{Context, Poll};
8
9const WRITE_LOCKED: isize = -1;
15
16#[repr(align(64))]
19pub struct RwLock<T: ?Sized> {
20 state: AtomicIsize,
21 wait: WaitQueue,
22 data: UnsafeCell<T>,
23}
24
25unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
30unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
31
32impl<T> RwLock<T> {
33 #[must_use]
35 pub const fn new(data: T) -> Self {
36 Self {
37 state: AtomicIsize::new(0),
38 wait: WaitQueue::new(),
39 data: UnsafeCell::new(data),
40 }
41 }
42
43 #[inline(always)]
45 pub fn into_inner(self) -> T {
46 self.data.into_inner()
47 }
48}
49
50impl<T: ?Sized + Send + Sync> RwLock<T> {
51 #[inline(always)]
54 pub async fn read(&self) -> RwLockReadGuard<'_, T> {
55 std::future::poll_fn(|cx| self.poll_read(cx)).await
56 }
57
58 #[inline(always)]
61 pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
62 std::future::poll_fn(|cx| self.poll_write(cx)).await
63 }
64}
65
66impl<T: ?Sized> RwLock<T> {
67 #[must_use]
69 #[inline(always)]
70 pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
71 self.try_acquire_read()
76 .then(|| RwLockReadGuard { lock: self })
77 }
78
79 #[must_use]
81 #[inline(always)]
82 pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> {
83 self.state
84 .compare_exchange(0, WRITE_LOCKED, Ordering::Acquire, Ordering::Relaxed)
85 .is_ok()
86 .then(|| RwLockWriteGuard { lock: self })
87 }
88
89 #[inline(always)]
90 fn try_acquire_read(&self) -> bool {
91 let mut current = self.state.load(Ordering::Relaxed);
92 loop {
93 if current < 0 {
94 return false;
95 }
96 match self.state.compare_exchange_weak(
97 current,
98 current + 1,
99 Ordering::Acquire,
100 Ordering::Relaxed,
101 ) {
102 Ok(_) => return true,
103 Err(observed) => current = observed,
104 }
105 }
106 }
107
108 #[inline(always)]
109 fn poll_read(&self, cx: &Context<'_>) -> Poll<RwLockReadGuard<'_, T>> {
110 if self.try_acquire_read() {
111 return Poll::Ready(RwLockReadGuard { lock: self });
112 }
113 let token = self.wait.register(cx.waker());
116 if self.try_acquire_read() {
117 self.wait.cancel(token);
118 return Poll::Ready(RwLockReadGuard { lock: self });
119 }
120 Poll::Pending
121 }
122
123 #[inline(always)]
124 fn poll_write(&self, cx: &Context<'_>) -> Poll<RwLockWriteGuard<'_, T>> {
125 if !self.wait.has_waiters()
133 && let Some(guard) = self.try_write()
134 {
135 return Poll::Ready(guard);
136 }
137 let token = self.wait.register(cx.waker());
138 if let Some(guard) = self.try_write() {
139 self.wait.cancel(token);
140 return Poll::Ready(guard);
141 }
142 Poll::Pending
143 }
144
145 pub const fn get_mut(&mut self) -> &mut T {
148 self.data.get_mut()
149 }
150}
151
152impl<T: Default> Default for RwLock<T> {
153 fn default() -> Self {
154 Self {
155 state: AtomicIsize::new(0),
156 wait: WaitQueue::new(),
157 data: UnsafeCell::new(T::default()),
158 }
159 }
160}
161
162#[repr(align(64))]
164pub struct RwLockReadGuard<'a, T: ?Sized> {
165 lock: &'a RwLock<T>,
166}
167
168unsafe impl<T: ?Sized + Sync> Send for RwLockReadGuard<'_, T> {}
169unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {}
170
171impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
172 type Target = T;
173 #[inline(always)]
174 fn deref(&self) -> &T {
175 unsafe { &*self.lock.data.get() }
177 }
178}
179
180impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
181 #[inline(always)]
182 fn drop(&mut self) {
183 let prev = self.lock.state.fetch_sub(1, Ordering::Release);
184 if prev == 1 {
188 self.lock.wait.wake_all();
189 }
190 }
191}
192
193#[repr(align(64))]
195pub struct RwLockWriteGuard<'a, T: ?Sized> {
196 lock: &'a RwLock<T>,
197}
198
199unsafe impl<T: ?Sized + Send> Send for RwLockWriteGuard<'_, T> {}
200unsafe impl<T: ?Sized + Sync> Sync for RwLockWriteGuard<'_, T> {}
201
202impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
203 type Target = T;
204 #[inline(always)]
205 fn deref(&self) -> &T {
206 unsafe { &*self.lock.data.get() }
208 }
209}
210
211impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
212 #[inline(always)]
213 fn deref_mut(&mut self) -> &mut T {
214 unsafe { &mut *self.lock.data.get() }
216 }
217}
218
219impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
220 #[inline(always)]
221 fn drop(&mut self) {
222 self.lock.state.store(0, Ordering::Release);
223 self.lock.wait.wake_all();
224 }
225}