/// A guard that provides read access to snatchable data. pubstruct SnatchGuard<'a>(RwLockReadGuard<'a, ()>); /// A guard that allows snatching the snatchable data. pubstruct ExclusiveSnatchGuard<'a>(#[expect(dead_code)] RwLockWriteGuard<'a, ()>);
/// A value that is mostly immutable but can be "snatched" if we need to destroy /// it early. /// /// In order to safely access the underlying data, the device's global snatchable /// lock must be taken. To guarantee it, methods take a read or write guard of that /// special lock. pubstruct Snatchable<T> {
value: UnsafeCell<Option<T>>,
}
/// Get read access to the value. Requires a the snatchable lock's read guard. pubfn get<'a>(&'a self, _guard: &'a SnatchGuard) -> Option<&'>a T> { unsafe { (*self.value.get()).as_ref() }
}
/// Take the value. Requires a the snatchable lock's write guard. pubfn snatch(&self, _guard: &mut ExclusiveSnatchGuard) -> Option<T> { unsafe { (*self.value.get()).take() }
}
/// Take the value without a guard. This can only be used with exclusive access /// to self, so it does not require locking. /// /// Typically useful in a drop implementation. pubfn take(&mutself) -> Option<T> { self.value.get_mut().take()
}
}
// Can't safely print the contents of a snatchable object without holding // the lock. impl<T> fmt::Debug for Snatchable<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<snatchable>")
}
}
unsafeimpl<T> Sync for Snatchable<T> {}
use trace::LockTrace; #[cfg(all(debug_assertions, feature = "std"))] mod trace { use core::{cell::Cell, fmt, panic::Location}; use std::{backtrace::Backtrace, thread};
iflet Some(prev) = SNATCH_LOCK_TRACE.take() { let current = thread::current(); let name = current.name().unwrap_or("<unnamed>");
panic!( "thread '{name}' attempted to acquire a snatch lock recursively.\n\
- Currently trying to acquire {new}\n\
- Previously acquired {prev}",
);
} else {
SNATCH_LOCK_TRACE.set(Some(new));
}
}
/// A Device-global lock for all snatchable data. pubstruct SnatchLock {
lock: RwLock<()>,
}
impl SnatchLock { /// The safety of `Snatchable::get` and `Snatchable::snatch` rely on their using of the /// right SnatchLock (the one associated to the same device). This method is unsafe /// to force force sers to think twice about creating a SnatchLock. The only place this /// method should be called is when creating the device. pubunsafefn new(rank: rank::LockRank) -> Self {
SnatchLock {
lock: RwLock::new(rank, ()),
}
}
/// Request write access to snatchable resources. /// /// This should only be called when a resource needs to be snatched. This has /// a high risk of causing lock contention if called concurrently with other /// wgpu work. #[track_caller] pubfn write(&self) -> ExclusiveSnatchGuard<'_> {
LockTrace::enter("write");
ExclusiveSnatchGuard(self.lock.write())
}
#[track_caller] pubunsafefn force_unlock_read(&self, data: RankData) { // This is unsafe because it can cause deadlocks if the lock is held. // It should only be used in very specific cases, like when a resource // needs to be snatched in a panic handler.
LockTrace::exit(); unsafe { self.lock.force_unlock_read(data) };
}
}
impl SnatchGuard<'_> { /// Forget the guard, leaving the lock in a locked state with no guard. /// /// This is equivalent to `std::mem::forget`, but preserves the information about the lock /// rank. pubfn forget(this: Self) -> RankData { // Cancel the drop implementation of the current guard. let manually_drop = ManuallyDrop::new(this);
// As we are unable to destructure out of this guard due to the drop implementation, // so we manually read the inner value. // SAFETY: This is safe because we never access the original guard again. let inner_guard = unsafe { core::ptr::read(&manually_drop.0) };
RwLockReadGuard::forget(inner_guard)
}
}
impl Drop for SnatchGuard<'_> { fn drop(&mutself) {
LockTrace::exit();
}
}
impl Drop for ExclusiveSnatchGuard<'_> { fn drop(&mutself) {
LockTrace::exit();
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-08-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.