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