Skip to main content

chaud_hot/func/
atomic.rs

1use super::{ErasedFnPtr, ErasedFnPtrPointee};
2use core::sync::atomic::{AtomicPtr, Ordering::Relaxed};
3
4#[repr(transparent)]
5pub struct AtomicFnPtr {
6    /// # Safety
7    ///
8    /// See the [module][super#safety] docs:
9    ///
10    /// * The actual type must never change.
11    /// * The actual type must be a function pointer implementing
12    ///   [`super::FnPtrLike`].
13    inner: AtomicPtr<ErasedFnPtrPointee>,
14}
15
16impl AtomicFnPtr {
17    #[inline]
18    #[must_use]
19    pub(super) const fn new(f: ErasedFnPtr) -> Self {
20        // SAFETY: Initializing defines the actual type stored. The other
21        // requirements are enforced by `ErasedFnPtr`.
22        Self { inner: AtomicPtr::new(f.raw()) }
23    }
24
25    /// # SAFETY
26    ///
27    /// The passed argument must have the same actual type as `self`.
28    #[inline]
29    pub(super) unsafe fn store_relaxed(&self, f: ErasedFnPtr) {
30        // SAFETY: The caller must ensure that `f` has the same actual type as
31        // `self`.
32        self.inner.store(f.raw(), Relaxed);
33    }
34
35    #[inline]
36    #[must_use]
37    pub(super) fn load_relaxed(&self) -> ErasedFnPtr {
38        let inner = self.inner.load(Relaxed);
39
40        // SAFETY: The actual type stored is a function pointer implementing
41        // `FnPtr`.
42        unsafe { ErasedFnPtr::from_raw_never_null(inner) }
43    }
44}