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}