rill_core/buffer/
storage.rs1use std::cell::UnsafeCell;
8use std::fmt;
9
10#[repr(transparent)]
19pub struct AtomicCell<T> {
20 inner: UnsafeCell<T>,
21}
22
23#[allow(unsafe_code)]
24impl<T> AtomicCell<T> {
25 #[inline]
27 pub fn load(&self) -> T
28 where
29 T: Copy,
30 {
31 unsafe { *self.inner.get() }
36 }
37
38 #[inline]
40 pub fn store(&self, value: T) {
41 unsafe {
46 *self.inner.get() = value;
47 }
48 }
49
50 #[inline]
52 pub fn as_ptr(&self) -> *mut T {
53 self.inner.get()
54 }
55
56 #[inline]
58 pub const fn new(value: T) -> Self {
59 Self {
60 inner: UnsafeCell::new(value),
61 }
62 }
63
64 pub fn try_new(value: T) -> Result<Self, AtomicCellError> {
69 if std::mem::size_of::<T>() > isize::MAX as usize {
70 return Err(AtomicCellError::TypeTooLarge);
71 }
72 Ok(Self::new(value))
73 }
74}
75
76impl<T: Clone + Copy> Clone for AtomicCell<T> {
77 fn clone(&self) -> Self {
78 Self::new(self.load())
79 }
80}
81
82impl<T: Copy + fmt::Debug> fmt::Debug for AtomicCell<T> {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.debug_struct("AtomicCell")
85 .field("value", &self.load())
86 .finish()
87 }
88}
89
90impl<T: Default> Default for AtomicCell<T> {
91 fn default() -> Self {
92 Self::new(T::default())
93 }
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub enum AtomicCellError {
99 TypeTooLarge,
101 OutOfMemory,
103}
104
105impl fmt::Display for AtomicCellError {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 match self {
108 AtomicCellError::TypeTooLarge => write!(f, "Type too large for atomic cell"),
109 AtomicCellError::OutOfMemory => write!(f, "Out of memory"),
110 }
111 }
112}
113
114impl std::error::Error for AtomicCellError {}
115
116#[allow(unsafe_code)]
118unsafe impl<T: Send> Send for AtomicCell<T> {}
119#[allow(unsafe_code)]
120unsafe impl<T: Sync> Sync for AtomicCell<T> {}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_atomic_cell_basic() {
128 let cell = AtomicCell::new(42);
129 assert_eq!(cell.load(), 42);
130
131 cell.store(100);
132 assert_eq!(cell.load(), 100);
133 }
134
135 #[test]
136 fn test_atomic_cell_try_new() {
137 let cell = AtomicCell::try_new(42).unwrap();
138 assert_eq!(cell.load(), 42);
139 }
140
141 #[test]
142 fn test_atomic_cell_default() {
143 let cell = AtomicCell::<i32>::default();
144 assert_eq!(cell.load(), 0);
145 }
146
147 #[test]
148 fn test_atomic_cell_clone() {
149 let cell1 = AtomicCell::new(42);
150 let cell2 = cell1.clone();
151 assert_eq!(cell2.load(), 42);
152 }
153}