read_write_api/lib.rs
1use std::ops::{Deref, DerefMut};
2
3pub use wrappers::{ReadApiWrapper, RwApiWrapper, RwApiWrapperOwned};
4
5mod impls;
6mod wrappers;
7
8/// Provides an interface to unify single-threaded code and RwLocks-based code.
9///
10/// A nice side effect of this trait is manifested in the activation
11/// of the borrow-checker to check the absence of deadlocks introduced in the current scope.
12/// This is because `Self::write` can now only be called on a mutable,
13/// but not constant, reference.
14///
15/// # Example
16///
17/// ```rust
18/// use parking_lot::RwLock;
19/// use read_write_api::{
20/// DowngradableWriteGuard,
21/// RwApi,
22/// RwApiWrapper,
23/// RwApiWrapperOwned,
24/// UpgradableReadGuard,
25/// };
26///
27/// fn do_something(mut x: impl RwApi<Target=u64>) -> u64 {
28/// let guard = x.upgradable_read();
29/// if *guard == 1 {
30/// let mut guard = guard.upgrade_to_downgradable();
31/// *guard = 2;
32/// *guard.downgrade()
33/// } else {
34/// *guard
35/// }
36/// }
37///
38/// assert_eq!(do_something(RwApiWrapperOwned(1)), 2);
39/// assert_eq!(do_something(RwApiWrapperOwned(3)), 3);
40/// assert_eq!(do_something(&mut RwApiWrapperOwned(1)), 2);
41/// assert_eq!(do_something(&mut RwApiWrapperOwned(3)), 3);
42///
43/// assert_eq!(do_something(RwLock::new(1)), 2);
44/// assert_eq!(do_something(RwLock::new(3)), 3);
45/// assert_eq!(do_something(&RwLock::new(1)), 2);
46/// assert_eq!(do_something(&RwLock::new(3)), 3);
47/// assert_eq!(do_something(&mut RwLock::new(1)), 2);
48/// assert_eq!(do_something(&mut RwLock::new(3)), 3);
49///
50/// fn do_something_ref<'a>(mut x: impl RwApi<Target=&'a mut u64>) -> u64 {
51/// if **x.read() == 1 {
52/// **x.write() = 2;
53/// **x.read()
54/// } else {
55/// **x.read()
56/// }
57/// }
58///
59/// assert_eq!(do_something_ref(RwApiWrapper(&mut 1)), 2);
60/// assert_eq!(do_something_ref(RwApiWrapper(&mut 3)), 3);
61/// assert_eq!(do_something_ref(&mut RwApiWrapper(&mut 1)), 2);
62/// assert_eq!(do_something_ref(&mut RwApiWrapper(&mut 3)), 3);
63///
64/// assert_eq!(do_something_ref(RwLock::new(&mut 1)), 2);
65/// assert_eq!(do_something_ref(RwLock::new(&mut 3)), 3);
66/// assert_eq!(do_something_ref(&RwLock::new(&mut 1)), 2);
67/// assert_eq!(do_something_ref(&RwLock::new(&mut 3)), 3);
68/// assert_eq!(do_something_ref(&mut RwLock::new(&mut 1)), 2);
69/// assert_eq!(do_something_ref(&mut RwLock::new(&mut 3)), 3);
70/// ```
71pub trait RwApi: ReadApi + WriteApi + UpgradableReadApi + DowngradableWriteApi {}
72
73/// Provides a constant part of the [`RwApi`] interface.
74///
75/// # Example
76///
77/// ```rust
78/// use std::ops::Deref;
79/// use parking_lot::RwLock;
80/// use read_write_api::{ReadApi, RwApi, RwApiWrapper, RwApiWrapperOwned};
81///
82/// fn do_something(mut x: impl RwApi<Target=u64>) -> u64 {
83/// if *x.read() == 1 {
84/// *x.write() = 2;
85/// read_x(&x)
86/// } else {
87/// read_x(&x)
88/// }
89/// }
90///
91/// fn read_x(x: &impl ReadApi<Target=u64>) -> u64 {
92/// *x.read()
93/// }
94///
95/// assert_eq!(do_something(RwApiWrapperOwned(1)), 2);
96/// assert_eq!(do_something(RwApiWrapperOwned(3)), 3);
97/// assert_eq!(do_something(&mut RwApiWrapperOwned(1)), 2);
98/// assert_eq!(do_something(&mut RwApiWrapperOwned(3)), 3);
99///
100/// assert_eq!(do_something(RwLock::new(1)), 2);
101/// assert_eq!(do_something(RwLock::new(3)), 3);
102/// assert_eq!(do_something(&RwLock::new(1)), 2);
103/// assert_eq!(do_something(&RwLock::new(3)), 3);
104/// assert_eq!(do_something(&mut RwLock::new(1)), 2);
105/// assert_eq!(do_something(&mut RwLock::new(3)), 3);
106///
107/// fn do_something_ref<'a>(mut x: impl RwApi<Target=&'a mut u64>) -> u64 {
108/// if **x.read() == 1 {
109/// **x.write() = 2;
110/// read_x_ref(&x)
111/// } else {
112/// read_x_ref(&x)
113/// }
114/// }
115///
116/// fn read_x_ref<T>(x: &impl ReadApi<Target=T>) -> u64
117/// where
118/// T: Deref<Target=u64>
119/// {
120/// **x.read()
121/// }
122///
123/// assert_eq!(do_something_ref(RwApiWrapper(&mut 1)), 2);
124/// assert_eq!(do_something_ref(RwApiWrapper(&mut 3)), 3);
125/// assert_eq!(do_something_ref(&mut RwApiWrapper(&mut 1)), 2);
126/// assert_eq!(do_something_ref(&mut RwApiWrapper(&mut 3)), 3);
127///
128/// assert_eq!(do_something_ref(RwLock::new(&mut 1)), 2);
129/// assert_eq!(do_something_ref(RwLock::new(&mut 3)), 3);
130/// assert_eq!(do_something_ref(&RwLock::new(&mut 1)), 2);
131/// assert_eq!(do_something_ref(&RwLock::new(&mut 3)), 3);
132/// assert_eq!(do_something_ref(&mut RwLock::new(&mut 1)), 2);
133/// assert_eq!(do_something_ref(&mut RwLock::new(&mut 3)), 3);
134/// ```
135pub trait ReadApi: GuardedTarget
136{
137 /// [`Self::read`] return type.
138 type ReadGuard<'a>: Deref<Target=Self::Target>
139 where Self: 'a;
140
141 /// Generalizes [`RwLock::read`](parking_lot::RwLock::read).
142 fn read(&self) -> Self::ReadGuard<'_>;
143}
144
145/// Provides a mutable part of the [`RwApi`] interface.
146///
147/// # Example
148///
149/// ```rust
150/// use std::ops::Deref;
151/// use parking_lot::RwLock;
152/// use read_write_api::{RwApi, RwApiWrapper, RwApiWrapperOwned, WriteApi};
153///
154/// fn do_something(mut x: impl RwApi<Target=u64>) -> u64 {
155/// if *x.read() == 1 {
156/// *write_x(&mut x) = 2;
157/// *x.read()
158/// } else {
159/// *x.read()
160/// }
161/// }
162///
163/// fn write_x<T: WriteApi>(x: &mut T) -> T::WriteGuard<'_> {
164/// x.write()
165/// }
166///
167/// assert_eq!(do_something(RwApiWrapperOwned(1)), 2);
168/// assert_eq!(do_something(RwApiWrapperOwned(3)), 3);
169/// assert_eq!(do_something(&mut RwApiWrapperOwned(1)), 2);
170/// assert_eq!(do_something(&mut RwApiWrapperOwned(3)), 3);
171///
172/// assert_eq!(do_something(RwLock::new(1)), 2);
173/// assert_eq!(do_something(RwLock::new(3)), 3);
174/// assert_eq!(do_something(&RwLock::new(1)), 2);
175/// assert_eq!(do_something(&RwLock::new(3)), 3);
176/// assert_eq!(do_something(&mut RwLock::new(1)), 2);
177/// assert_eq!(do_something(&mut RwLock::new(3)), 3);
178///
179/// fn do_something_ref<'a>(mut x: impl RwApi<Target=&'a mut u64>) -> u64 {
180/// if **x.read() == 1 {
181/// **write_x(&mut x) = 2;
182/// **x.read()
183/// } else {
184/// **x.read()
185/// }
186/// }
187///
188/// assert_eq!(do_something_ref(RwApiWrapper(&mut 1)), 2);
189/// assert_eq!(do_something_ref(RwApiWrapper(&mut 3)), 3);
190/// assert_eq!(do_something_ref(&mut RwApiWrapper(&mut 1)), 2);
191/// assert_eq!(do_something_ref(&mut RwApiWrapper(&mut 3)), 3);
192///
193/// assert_eq!(do_something_ref(RwLock::new(&mut 1)), 2);
194/// assert_eq!(do_something_ref(RwLock::new(&mut 3)), 3);
195/// assert_eq!(do_something_ref(&RwLock::new(&mut 1)), 2);
196/// assert_eq!(do_something_ref(&RwLock::new(&mut 3)), 3);
197/// assert_eq!(do_something_ref(&mut RwLock::new(&mut 1)), 2);
198/// assert_eq!(do_something_ref(&mut RwLock::new(&mut 3)), 3);
199/// ```
200pub trait WriteApi: GuardedTarget
201{
202 /// [`Self::write`] return type.
203 type WriteGuard<'a>: DerefMut<Target=Self::Target>
204 where Self: 'a;
205
206 /// Generalizes [`RwLock::write`](parking_lot::RwLock::write).
207 fn write(&mut self) -> Self::WriteGuard<'_>;
208}
209
210/// Provides a constant (but upgradable) part of the [`RwApi`] interface.
211///
212/// # Example
213///
214/// See the [`RwApi`] docs for usage examples.
215pub trait UpgradableReadApi: GuardedTarget
216{
217 /// [`Self::upgradable_read`] return type.
218 type UpgradableReadGuard<'a>: UpgradableReadGuard<Target=Self::Target>
219 where Self: 'a;
220
221 /// Generalizes
222 /// [`RwLock::upgradable_read`](parking_lot::RwLock::upgradable_read).
223 fn upgradable_read(&mut self) -> Self::UpgradableReadGuard<'_>;
224}
225
226/// Provides a mutable (but downgradable) part of the [`RwApi`] interface.
227///
228/// # Example
229///
230/// See the [`RwApi`] docs for usage examples.
231pub trait DowngradableWriteApi: GuardedTarget
232{
233 /// [`Self::downgradable_write`] return type.
234 type DowngradableWriteGuard<'a>: DowngradableWriteGuard<Target=Self::Target>
235 where Self: 'a;
236
237 /// [`WriteApi::write`] analogue, which return type can be downgraded.
238 fn downgradable_write(&mut self) -> Self::DowngradableWriteGuard<'_>;
239}
240
241/// Provides an interface for upgrading upgradable read guards.
242///
243/// # Example
244///
245/// See the [`GuardedTarget`] docs for implementation examples.
246pub trait UpgradableReadGuard: Deref
247{
248 /// [`Self::upgrade`] return type.
249 type UpgradeResult: DerefMut<Target=Self::Target>;
250
251 /// [`Self::upgrade_to_downgradable`] return type.
252 type UpgradeToDowngradableResult: DowngradableWriteGuard<
253 DowngradeToUpgradableResult=Self,
254 Target=Self::Target
255 >;
256
257 /// Generalizes
258 /// [`RwLockUpgradableReadGuard::upgrade`](parking_lot::RwLockUpgradableReadGuard::upgrade).
259 fn upgrade(self) -> Self::UpgradeResult;
260
261 /// [`Self::upgrade`] analogue, which return type can be downgraded.
262 fn upgrade_to_downgradable(self) -> Self::UpgradeToDowngradableResult;
263}
264
265/// Provides an interface for downgrading downgradable write guards.
266///
267/// # Example
268///
269/// See the [`GuardedTarget`] docs for implementation examples.
270pub trait DowngradableWriteGuard: DerefMut
271{
272 /// [`Self::downgrade`] return type.
273 type DowngradeResult: Deref<Target=Self::Target>;
274
275 /// [`Self::downgrade_to_upgradable`] return type.
276 type DowngradeToUpgradableResult: UpgradableReadGuard<
277 UpgradeToDowngradableResult=Self,
278 Target=Self::Target
279 >;
280
281 /// Downgrades the write guard to a read guard.
282 fn downgrade(self) -> Self::DowngradeResult;
283
284 /// Downgrades the write guard to an upgradable read guard.
285 fn downgrade_to_upgradable(self) -> Self::DowngradeToUpgradableResult;
286}
287
288/// Provides a single dereferencing target type for
289/// the [`ReadApi`], [`WriteApi`] and [`RwApi`] traits.
290///
291/// # Example
292///
293/// ```rust
294/// use read_write_api::{
295/// DowngradableWriteApi,
296/// GuardedTarget,
297/// ReadApi,
298/// RwApi,
299/// UpgradableReadApi,
300/// WriteApi
301/// };
302///
303/// struct A(u64);
304///
305/// impl GuardedTarget for A {
306/// type Target = u64;
307/// }
308///
309/// impl ReadApi for A
310/// {
311/// type ReadGuard<'a> = &'a u64
312/// where Self: 'a;
313///
314/// fn read(&self) -> Self::ReadGuard<'_> {
315/// &self.0
316/// }
317/// }
318///
319/// impl WriteApi for A
320/// {
321/// type WriteGuard<'a> = &'a mut u64
322/// where Self: 'a;
323///
324/// fn write(&mut self) -> Self::WriteGuard<'_> {
325/// &mut self.0
326/// }
327/// }
328///
329/// impl UpgradableReadApi for A
330/// {
331/// type UpgradableReadGuard<'a> = &'a mut u64
332/// where Self: 'a;
333///
334/// fn upgradable_read(&mut self) -> Self::UpgradableReadGuard<'_> {
335/// &mut self.0
336/// }
337/// }
338///
339/// impl DowngradableWriteApi for A
340/// {
341/// type DowngradableWriteGuard<'a> = &'a mut u64
342/// where Self: 'a;
343///
344/// fn downgradable_write(&mut self) -> Self::DowngradableWriteGuard<'_> {
345/// &mut self.0
346/// }
347/// }
348///
349/// fn accept_read_write(_: impl RwApi<Target=u64>) {}
350///
351/// accept_read_write(A(1))
352/// ```
353pub trait GuardedTarget
354{
355 /// Dereferencing target of the read and write guards.
356 type Target;
357}
358
359#[cfg(doctest)]
360mod test_readme
361{
362 macro_rules! external_doc_test {
363 ($x:expr) => {
364 #[doc = $x]
365 extern {}
366 };
367 }
368
369 external_doc_test!(include_str!("../README.md"));
370}