zencan_common/
atomic_cell.rs1use core::{cell::Cell, ops::Add};
9use critical_section::Mutex;
10
11use crate::traits::LoadStore;
12
13pub struct AtomicCell<T> {
15 inner: Mutex<Cell<T>>,
16}
17
18impl<T: Send + Copy> AtomicCell<T> {
19 pub fn load(&self) -> T {
21 critical_section::with(|cs| self.inner.borrow(cs).get())
22 }
23
24 pub fn borrow<'a>(&'a self, cs: critical_section::CriticalSection<'a>) -> &'a Cell<T> {
28 self.inner.borrow(cs)
29 }
30
31 pub fn fetch_update(&self, mut f: impl FnMut(T) -> Option<T>) -> Result<T, T> {
36 critical_section::with(|cs| {
37 let old_value = self.inner.borrow(cs).get();
38 if let Some(new_value) = f(old_value) {
39 self.inner.borrow(cs).set(new_value);
40 Ok(old_value)
41 } else {
42 Err(old_value)
43 }
44 })
45 }
46}
47
48impl<T: Send> AtomicCell<T> {
49 pub const fn new(value: T) -> Self {
51 Self {
52 inner: Mutex::new(Cell::new(value)),
53 }
54 }
55
56 pub fn store(&self, value: T) {
58 critical_section::with(|cs| self.inner.borrow(cs).set(value));
59 }
60}
61
62impl<T: Send + Default> AtomicCell<T> {
63 pub fn take(&self) -> T {
65 critical_section::with(|cs| self.inner.borrow(cs).take())
66 }
67}
68
69impl<T: Copy + Add<Output = T>> AtomicCell<T> {
70 pub fn fetch_add(&self, value: T) -> T {
72 critical_section::with(|cs| {
73 let old_value = self.inner.borrow(cs).get();
74 self.inner.borrow(cs).set(old_value + value);
75 old_value
76 })
77 }
78}
79
80impl<T: Default> Default for AtomicCell<T> {
81 fn default() -> Self {
82 Self {
83 inner: Mutex::new(Cell::new(T::default())),
84 }
85 }
86}
87
88impl<T: Default + Copy + Send> LoadStore<T> for AtomicCell<T> {
89 fn load(&self) -> T {
90 self.load()
91 }
92
93 fn store(&self, value: T) {
94 self.store(value)
95 }
96}