1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! Clever hacks
use std::{marker::PhantomData, mem::ManuallyDrop};
use lock_api::{RawRwLock, RawRwLockDowngrade, RwLockReadGuard, RwLockWriteGuard};
pub(crate) fn try_map<F, T: ?Sized, U: ?Sized>(mut t: &mut T, f: F) -> Result<&mut U, &mut T>
where
F: FnOnce(&mut T) -> Option<&mut U>,
{
use polonius_the_crab::{polonius, polonius_return};
polonius!(|t| -> Result<&'polonius mut U, &mut T> {
if let Some(u) = f(t) {
polonius_return!(Ok(u));
}
});
Err(t)
}
/// A [`RwLockReadGuard`], without the data
pub(crate) struct RwLockReadGuardDetached<'a, R: RawRwLock> {
lock: &'a R,
_marker: PhantomData<R::GuardMarker>,
}
impl<R: RawRwLock> Drop for RwLockReadGuardDetached<'_, R> {
fn drop(&mut self) {
// Safety: An RwLockReadGuardDetached always holds a shared lock.
unsafe {
self.lock.unlock_shared();
}
}
}
/// A [`RwLockWriteGuard`], without the data
pub(crate) struct RwLockWriteGuardDetached<'a, R: RawRwLock> {
lock: &'a R,
_marker: PhantomData<R::GuardMarker>,
}
impl<R: RawRwLock> Drop for RwLockWriteGuardDetached<'_, R> {
fn drop(&mut self) {
// Safety: An RwLockWriteGuardDetached always holds an exclusive lock.
unsafe {
self.lock.unlock_exclusive();
}
}
}
impl<'a, R: RawRwLock> RwLockReadGuardDetached<'a, R> {
/// Separates the data from the [`RwLockReadGuard`]
///
/// # Safety
///
/// The data must not outlive the detached guard
pub(crate) unsafe fn detach_from<T>(guard: RwLockReadGuard<'a, R, T>) -> (Self, &'a T) {
let rwlock = RwLockReadGuard::rwlock(&ManuallyDrop::new(guard));
// Safety: There will be no concurrent writes as we are "forgetting" the existing guard,
// with the safety assumption that the caller will not drop the new detached guard early.
let data = unsafe { &*rwlock.data_ptr() };
let guard = RwLockReadGuardDetached {
// Safety: We are imitating the original RwLockReadGuard. It's the callers
// responsibility to not drop the guard early.
lock: unsafe { rwlock.raw() },
_marker: PhantomData,
};
(guard, data)
}
}
impl<'a, R: RawRwLock> RwLockWriteGuardDetached<'a, R> {
/// Separates the data from the [`RwLockWriteGuard`]
///
/// # Safety
///
/// The data must not outlive the detached guard
pub(crate) unsafe fn detach_from<T>(guard: RwLockWriteGuard<'a, R, T>) -> (Self, &'a mut T) {
let rwlock = RwLockWriteGuard::rwlock(&ManuallyDrop::new(guard));
// Safety: There will be no concurrent reads/writes as we are "forgetting" the existing guard,
// with the safety assumption that the caller will not drop the new detached guard early.
let data = unsafe { &mut *rwlock.data_ptr() };
let guard = RwLockWriteGuardDetached {
// Safety: We are imitating the original RwLockWriteGuard. It's the callers
// responsibility to not drop the guard early.
lock: unsafe { rwlock.raw() },
_marker: PhantomData,
};
(guard, data)
}
}
impl<'a, R: RawRwLockDowngrade> RwLockWriteGuardDetached<'a, R> {
/// # Safety
///
/// The associated data must not mut mutated after downgrading
pub(crate) unsafe fn downgrade(self) -> RwLockReadGuardDetached<'a, R> {
// Do not drop the write guard - otherwise we will trigger a downgrade + unlock_exclusive,
// which is incorrect
let this = ManuallyDrop::new(self);
// Safety: An RwLockWriteGuardDetached always holds an exclusive lock.
unsafe { this.lock.downgrade() }
RwLockReadGuardDetached {
lock: this.lock,
_marker: this._marker,
}
}
}