Skip to main content

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            {
    ::core::panicking::panic_fmt(format_args!("aborting due to panic while changing lock ownership"));
};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> {}