pinned/rwlock/write_guard.rs
1use std::cell::RefMut;
2use std::ops::{Deref, DerefMut};
3
4use super::wakers::WakeGuard;
5
6/// RAII structure used to release the exclusive write access of a lock when dropped.
7///
8/// This structure is created by the `write` method on [`RwLock`](super::RwLock).
9#[derive(Debug)]
10pub struct RwLockWriteGuard<'a, T: ?Sized> {
11 pub(super) wake_guard: WakeGuard<'a>,
12 // RefMut has a must_not_suspend notation. However, this lint is unlikely to be enabled in the
13 // foreseeable future. When it becomes enabled, we can vendor a version of RefCell without the
14 // lint.
15 pub(super) val: RefMut<'a, T>,
16}
17
18impl<'a, T> RwLockWriteGuard<'a, T>
19where
20 T: ?Sized,
21{
22 /// Makes a new `RwLockWriteGuard` for a component of the locked data.
23 ///
24 /// This operation cannot fail as data is already locked.
25 ///
26 /// This is an associated function that needs to be used as `RwLockWriteGuard::map(...)`. A
27 /// method would interfere with methods of the same name on the contents of the underlying data
28 /// used through `Deref`.
29 pub fn map<U, F>(this: Self, f: F) -> RwLockWriteGuard<'a, U>
30 where
31 F: FnOnce(&mut T) -> &mut U,
32 U: ?Sized,
33 {
34 let Self { wake_guard, val } = this;
35
36 let val = RefMut::map(val, f);
37 RwLockWriteGuard { wake_guard, val }
38 }
39
40 /// Tries to make a new `RwLockWriteGuard` for a component of the locked data. Returns the
41 /// original write guard if the closure returns `None`.
42 ///
43 /// This operation cannot fail as data is already locked.
44 ///
45 /// This is an associated function that needs to be used as `RwLockWriteGuard::filter_map(...)`.
46 /// A method would interfere with methods of the same name on the contents of the underlying
47 /// data used through `Deref`.
48 ///
49 /// This function is not available before Rust 1.63.
50 #[rustversion::since(1.63)]
51 pub fn filter_map<U, F>(this: Self, f: F) -> Result<RwLockWriteGuard<'a, U>, Self>
52 where
53 F: FnOnce(&mut T) -> Option<&mut U>,
54 U: ?Sized,
55 {
56 let Self { wake_guard, val } = this;
57
58 match RefMut::filter_map(val, f) {
59 Ok(val) => Ok(RwLockWriteGuard { wake_guard, val }),
60 Err(val) => Err(RwLockWriteGuard { wake_guard, val }),
61 }
62 }
63}
64
65impl<T> Deref for RwLockWriteGuard<'_, T>
66where
67 T: ?Sized,
68{
69 type Target = T;
70
71 fn deref(&self) -> &Self::Target {
72 self.val.deref()
73 }
74}
75
76impl<T> DerefMut for RwLockWriteGuard<'_, T> {
77 fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
78 self.val.deref_mut()
79 }
80}