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}