1use std::{marker::PhantomData, mem::ManuallyDrop};
4
5use lock_api::{RawRwLock, RawRwLockDowngrade, RwLockReadGuard, RwLockWriteGuard};
6
7pub(crate) fn try_map<F, T: ?Sized, U: ?Sized>(mut t: &mut T, f: F) -> Result<&mut U, &mut T>
8where
9 F: FnOnce(&mut T) -> Option<&mut U>,
10{
11 use polonius_the_crab::{polonius, polonius_return};
12 polonius!(|t| -> Result<&'polonius mut U, &mut T> {
13 if let Some(u) = f(t) {
14 polonius_return!(Ok(u));
15 }
16 });
17 Err(t)
18}
19
20pub(crate) struct RwLockReadGuardDetached<'a, R: RawRwLock> {
22 lock: &'a R,
23 _marker: PhantomData<R::GuardMarker>,
24}
25
26impl<R: RawRwLock> Drop for RwLockReadGuardDetached<'_, R> {
27 fn drop(&mut self) {
28 unsafe {
30 self.lock.unlock_shared();
31 }
32 }
33}
34
35pub(crate) struct RwLockWriteGuardDetached<'a, R: RawRwLock> {
37 lock: &'a R,
38 _marker: PhantomData<R::GuardMarker>,
39}
40
41impl<R: RawRwLock> Drop for RwLockWriteGuardDetached<'_, R> {
42 fn drop(&mut self) {
43 unsafe {
45 self.lock.unlock_exclusive();
46 }
47 }
48}
49
50impl<'a, R: RawRwLock> RwLockReadGuardDetached<'a, R> {
51 pub(crate) unsafe fn detach_from<T>(guard: RwLockReadGuard<'a, R, T>) -> (Self, &'a T) {
57 let rwlock = RwLockReadGuard::rwlock(&ManuallyDrop::new(guard));
58
59 let data = unsafe { &*rwlock.data_ptr() };
62 let guard = RwLockReadGuardDetached {
63 lock: unsafe { rwlock.raw() },
66 _marker: PhantomData,
67 };
68 (guard, data)
69 }
70}
71
72impl<'a, R: RawRwLock> RwLockWriteGuardDetached<'a, R> {
73 pub(crate) unsafe fn detach_from<T>(guard: RwLockWriteGuard<'a, R, T>) -> (Self, &'a mut T) {
79 let rwlock = RwLockWriteGuard::rwlock(&ManuallyDrop::new(guard));
80
81 let data = unsafe { &mut *rwlock.data_ptr() };
84 let guard = RwLockWriteGuardDetached {
85 lock: unsafe { rwlock.raw() },
88 _marker: PhantomData,
89 };
90 (guard, data)
91 }
92}
93
94impl<'a, R: RawRwLockDowngrade> RwLockWriteGuardDetached<'a, R> {
95 pub(crate) unsafe fn downgrade(self) -> RwLockReadGuardDetached<'a, R> {
99 let this = ManuallyDrop::new(self);
102
103 unsafe { this.lock.downgrade() }
105 RwLockReadGuardDetached {
106 lock: this.lock,
107 _marker: this._marker,
108 }
109 }
110}