department/statics/
cell.rs1use core::cell::UnsafeCell;
2use core::ptr::NonNull;
3use core::sync::atomic::{AtomicBool, Ordering};
4
5use super::traits::StaticStorage;
6
7pub struct StorageCell<S>(UnsafeCell<S>, AtomicBool);
10
11impl<S> StorageCell<S> {
12 pub const fn new(val: S) -> StorageCell<S> {
14 StorageCell(UnsafeCell::new(val), AtomicBool::new(false))
15 }
16
17 pub fn try_claim<T>(&'static self) -> Option<T>
21 where
22 T: StaticStorage<S>,
23 {
24 if self.inner_try_claim() {
25 Some(T::take_cell(self))
26 } else {
27 None
28 }
29 }
30
31 pub fn claim<T>(&'static self) -> T
37 where
38 T: StaticStorage<S>,
39 {
40 self.try_claim::<T>()
41 .unwrap_or_else(|| panic!("StorageCell already claimed by existing storage"))
42 }
43
44 pub(crate) fn release(&self) {
45 assert!(self.inner_try_release(), "Couldn't release StorageCell");
46 }
47
48 fn inner_try_claim(&self) -> bool {
49 self.1
50 .compare_exchange(false, true, Ordering::SeqCst, Ordering::Acquire)
51 .map_or(false, |val| !val)
52 }
53
54 fn inner_try_release(&self) -> bool {
55 self.1
56 .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
57 .is_ok()
58 }
59
60 pub(super) unsafe fn as_ptr(&self) -> NonNull<S> {
61 debug_assert!(
62 self.1.load(Ordering::SeqCst),
63 "Cell accessed while not claimed"
64 );
65 unsafe { NonNull::new_unchecked(self.0.get()) }
67 }
68}
69
70unsafe impl<S: Send> Send for StorageCell<S> {}
73unsafe impl<S: Sync> Sync for StorageCell<S> {}
76
77impl<S> Default for StorageCell<S>
78where
79 S: Default,
80{
81 fn default() -> StorageCell<S> {
82 StorageCell::new(S::default())
83 }
84}