|
1 |
| -use core::{cell::UnsafeCell, fmt}; |
| 1 | +use core::{cell::UnsafeCell, fmt, mem::ManuallyDrop}; |
2 | 2 |
|
3 |
| -use crate::lock::{rank, RwLock, RwLockReadGuard, RwLockWriteGuard}; |
| 3 | +use crate::lock::{rank, RankData, RwLock, RwLockReadGuard, RwLockWriteGuard}; |
4 | 4 |
|
5 | 5 | /// A guard that provides read access to snatchable data.
|
6 |
| -pub struct SnatchGuard<'a>(#[expect(dead_code)] RwLockReadGuard<'a, ()>); |
| 6 | +pub struct SnatchGuard<'a>(RwLockReadGuard<'a, ()>); |
7 | 7 | /// A guard that allows snatching the snatchable data.
|
8 | 8 | pub struct ExclusiveSnatchGuard<'a>(#[expect(dead_code)] RwLockWriteGuard<'a, ()>);
|
9 | 9 |
|
@@ -158,6 +158,34 @@ impl SnatchLock {
|
158 | 158 | LockTrace::enter("write");
|
159 | 159 | ExclusiveSnatchGuard(self.lock.write())
|
160 | 160 | }
|
| 161 | + |
| 162 | + #[track_caller] |
| 163 | + #[expect(unused)] |
| 164 | + pub unsafe fn force_unlock_read(&self, data: RankData) { |
| 165 | + // This is unsafe because it can cause deadlocks if the lock is held. |
| 166 | + // It should only be used in very specific cases, like when a resource |
| 167 | + // needs to be snatched in a panic handler. |
| 168 | + LockTrace::exit(); |
| 169 | + unsafe { self.lock.force_unlock_read(data) }; |
| 170 | + } |
| 171 | +} |
| 172 | + |
| 173 | +impl SnatchGuard<'_> { |
| 174 | + /// Forget the guard, leaving the lock in a locked state with no guard. |
| 175 | + /// |
| 176 | + /// This is equivalent to `std::mem::forget`, but preserves the information about the lock |
| 177 | + /// rank. |
| 178 | + pub fn forget(this: Self) -> RankData { |
| 179 | + // Cancel the drop implementation of the current guard. |
| 180 | + let manually_drop = ManuallyDrop::new(this); |
| 181 | + |
| 182 | + // As we are unable to destructure out of this guard due to the drop implementation, |
| 183 | + // so we manually read the inner value. |
| 184 | + // SAFETY: This is safe because we never access the original guard again. |
| 185 | + let inner_guard = unsafe { core::ptr::read(&manually_drop.0) }; |
| 186 | + |
| 187 | + RwLockReadGuard::forget(inner_guard) |
| 188 | + } |
161 | 189 | }
|
162 | 190 |
|
163 | 191 | impl Drop for SnatchGuard<'_> {
|
|
0 commit comments