lock_api/guard.rs
1use core::ptr::NonNull;
2
3/// Runs `f`, aborting the process if it unwinds.
4///
5/// This is used for raw lock operations whose panic behavior would otherwise
6/// leave a safe guard with unknown lock ownership.
7#[inline]
8pub(crate) fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T {
9 struct AbortOnDrop;
10
11 impl Drop for AbortOnDrop {
12 fn drop(&mut self) {
13 panic!("aborting due to panic while changing lock ownership");
14 }
15 }
16
17 let guard = AbortOnDrop;
18 let result = f();
19 core::mem::forget(guard);
20 result
21}
22
23/// A raw pointer carrying shared guard access to `T`.
24pub(crate) struct SharedGuardData<T: ?Sized>(NonNull<T>);
25
26impl<T: ?Sized> SharedGuardData<T> {
27 #[inline]
28 pub(crate) fn new(data: &T) -> Self {
29 Self(NonNull::from(data))
30 }
31
32 #[inline]
33 pub(crate) unsafe fn as_ref(&self) -> &T {
34 unsafe { self.0.as_ref() }
35 }
36}
37
38// SAFETY: Moving this pointer between threads only permits shared access to `T`,
39// which is safe when `T: Sync`.
40unsafe impl<T: Sync + ?Sized> Send for SharedGuardData<T> {}
41// SAFETY: Sharing this pointer between threads only permits shared access to
42// `T`, which is safe when `T: Sync`.
43unsafe impl<T: Sync + ?Sized> Sync for SharedGuardData<T> {}
44
45/// A raw pointer carrying exclusive guard access to `T`.
46// This deliberately uses `*mut T` instead of `NonNull<T>` to preserve the
47// invariance of exclusive access over `T`.
48pub(crate) struct ExclusiveGuardData<T: ?Sized>(*mut T);
49
50impl<T: ?Sized> ExclusiveGuardData<T> {
51 #[inline]
52 pub(crate) fn new(data: &mut T) -> Self {
53 Self(data)
54 }
55
56 #[inline]
57 pub(crate) unsafe fn as_ref(&self) -> &T {
58 unsafe { self.0.as_ref_unchecked() }
59 }
60
61 #[inline]
62 pub(crate) unsafe fn as_mut(&mut self) -> &mut T {
63 unsafe { self.0.as_mut_unchecked() }
64 }
65}
66
67// SAFETY: Moving this pointer transfers exclusive access to `T`, which is safe
68// when `T: Send`.
69unsafe impl<T: Send + ?Sized> Send for ExclusiveGuardData<T> {}
70// SAFETY: A shared reference to this pointer only permits shared access to `T`,
71// which is safe when `T: Sync`.
72unsafe impl<T: Sync + ?Sized> Sync for ExclusiveGuardData<T> {}