1use core::{
2 ops::{Deref, DerefMut, Try},
3 pin::Pin,
4};
5
6use crate::cancellation::TrMayCancel;
7
8pub trait TrAsyncRwLock {
10 type Target: ?Sized;
11
12 fn acquire(&self) -> impl TrAcquire<'_, Self::Target>;
13}
14
15pub trait TrAcquire<'a, T>
16where
17 Self: 'a,
18 T: 'a + ?Sized,
19{
20 type ReaderGuard<'g>: TrReaderGuard<'a, 'g, T> where 'a: 'g;
21
22 type WriterGuard<'g>: TrWriterGuard<'a, 'g, T> where 'a: 'g;
23
24 type UpgradableGuard<'g>: TrUpgradableReaderGuard<'a, 'g, T> where 'a: 'g;
25
26 fn try_read<'g>(
27 self: Pin<&'g mut Self>,
28 ) -> impl Try<Output = Self::ReaderGuard<'g>>
29 where
30 'a: 'g;
31
32 fn try_write<'g>(
33 self: Pin<&'g mut Self>,
34 ) -> impl Try<Output = Self::WriterGuard<'g>>
35 where
36 'a: 'g;
37
38 fn try_upgradable_read<'g>(
39 self: Pin<&'g mut Self>,
40 ) -> impl Try<Output = Self::UpgradableGuard<'g>>
41 where
42 'a: 'g;
43
44 fn read_async<'g>(
45 self: Pin<&'g mut Self>,
46 ) -> impl TrMayCancel<'g,
47 MayCancelOutput: Try<Output = Self::ReaderGuard<'g>>>
48 where
49 'a: 'g;
50
51 fn write_async<'g>(
52 self: Pin<&'g mut Self>,
53 ) -> impl TrMayCancel<'g,
54 MayCancelOutput: Try<Output = Self::WriterGuard<'g>>>
55 where
56 'a: 'g;
57
58 fn upgradable_read_async<'g>(
59 self: Pin<&'g mut Self>,
60 ) -> impl TrMayCancel<'g,
61 MayCancelOutput: Try<Output = Self::UpgradableGuard<'g>>>
62 where
63 'a: 'g;
64}
65
66pub trait TrReaderGuard<'a, 'g, T>
67where
68 'a: 'g,
69 Self: 'g + Sized + Deref<Target = T>,
70 T: 'a + ?Sized,
71{
72 type Acquire: TrAcquire<'a, T>;
73
74 fn as_reader_guard(&self) -> &Self {
75 self
76 }
77}
78
79pub trait TrUpgradableReaderGuard<'a, 'g, T>
80where
81 'a: 'g,
82 Self: 'g + TrReaderGuard<'a, 'g, T>,
83 T: 'a + ?Sized,
84{
85 fn downgrade(self) -> <Self::Acquire as TrAcquire<'a, T>>::ReaderGuard<'g>;
86
87 fn upgrade(self) -> impl TrUpgrade<'a, 'g, T, Acquire = Self::Acquire>;
88}
89
90pub trait TrWriterGuard<'a, 'g, T>
91where
92 'a: 'g,
93 Self: 'g + TrReaderGuard<'a, 'g, T> + DerefMut<Target = T>,
94 T: 'a + ?Sized,
95{
96 fn downgrade(self) -> <Self::Acquire as TrAcquire<'a, T>>::ReaderGuard<'g>;
97
98 fn downgrade_to_upgradable(
99 self,
100 ) -> <Self::Acquire as TrAcquire<'a, T>>::UpgradableGuard<'g>;
101}
102
103pub trait TrUpgrade<'a, 'g, T>
104where
105 'a: 'g,
106 T: 'a + ?Sized,
107{
108 type Acquire: TrAcquire<'a, T>;
109
110 fn try_upgrade<'u>(
111 self: Pin<&'u mut Self>,
112 ) -> impl Try<Output = <Self::Acquire as TrAcquire<'a, T>>::WriterGuard<'u>>
113 where
114 'g: 'u;
115
116 fn upgrade_async<'u>(
117 self: Pin<&'u mut Self>,
118 ) -> impl TrMayCancel<'u, MayCancelOutput: Try<Output =
119 <Self::Acquire as TrAcquire<'a, T>>::WriterGuard<'u>>>
120 where
121 'g: 'u;
122
123 fn into_guard(
124 self,
125 ) -> <Self::Acquire as TrAcquire<'a, T>>::UpgradableGuard<'g>;
126}
127
128#[cfg(test)]
129mod demo_ {
130 use std::{
131 borrow::BorrowMut,
132 ops::{ControlFlow, Deref, DerefMut},
133 };
134 use pin_utils::pin_mut;
135
136 use crate::cancellation::{NonCancellableToken, TrMayCancel};
137
138 use super::*;
139
140 #[allow(dead_code)]
141 async fn generic_rwlock_smoke_<B, L, T>(rwlock: B)
142 where
143 B: BorrowMut<L>,
144 L: TrAsyncRwLock<Target = T>,
145 {
146 let acq = rwlock.borrow().acquire();
147 pin_mut!(acq);
148 let read_async = acq.as_mut().read_async();
149 let ControlFlow::Continue(read_guard) = read_async
151 .may_cancel_with(NonCancellableToken::pinned())
152 .await
153 .branch()
154 else {
155 panic!()
156 };
157 let _ = read_guard.deref();
158 drop(read_guard);
160 let ControlFlow::Continue(upgradable) = acq
161 .as_mut()
162 .upgradable_read_async()
163 .may_cancel_with(NonCancellableToken::pinned())
164 .await
165 .branch()
166 else {
167 panic!()
168 };
169 let _ = upgradable.deref();
170 let upgrade = upgradable.upgrade();
171 pin_mut!(upgrade);
172 let ControlFlow::Continue(mut write_guard) = upgrade
173 .upgrade_async()
174 .may_cancel_with(NonCancellableToken::pinned())
175 .await
176 .branch()
177 else {
178 panic!()
179 };
180 let _ = write_guard.deref_mut();
181 let upgradable = write_guard.downgrade_to_upgradable();
182 drop(upgradable)
183 }
184}