1#![no_std]
2use core::fmt;
3use core::mem::MaybeUninit;
4use core::ops::Deref;
5use core::ptr;
6use core::sync::atomic::Ordering::{Relaxed, SeqCst};
7use interrupt::CriticalSection;
8use util::*;
9
10pub struct Ref<'a, T>(&'a Cell<T>);
11impl<'a, T> Ref<'a, T> {
12    pub fn ref_num(&self) -> Result<usize, MemoryState> {
13        self.0.ref_num()
14    }
15    pub fn remove(&self) {
17        let _ = self.0.state.fetch_update(SeqCst, Relaxed, |mut x| {
18            x.set_state(MemoryState::Erasing);
19            Some(x)
20        });
21    }
22    pub fn will_remove(&self) -> bool {
23        self.0.state.load(SeqCst).state().is_erasing()
24    }
25}
26impl<'a, T> Deref for Ref<'a, T> {
27    type Target = T;
28    fn deref(&self) -> &Self::Target {
29        unsafe { self.0.val.assume_init_ref() }
30    }
31}
32impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
33    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34        let v: &T = &*self;
35        fmt::Debug::fmt(&v, f)
36    }
37}
38impl<'a, T> Drop for Ref<'a, T> {
39    fn drop(&mut self) {
40        let _cs = CriticalSection::new();
41        let old = match self.0.state.fetch_update(SeqCst, Relaxed, |mut x| {
42            if x.ref_sub().is_ok() {
43                Some(x)
44            } else {
45                None
46            }
47        }) {
48            Ok(v) => v,
49            Err(v) => v,
50        };
51        let will_drop = self.will_remove();
52        if old.ref_num() == Ok(1) && will_drop {
53            unsafe { ptr::drop_in_place(self.0.val.as_ptr() as *mut T) };
54            self.0
55                .state
56                .store(MemoryState::Uninitialized.into(), SeqCst);
57        }
58    }
59}
60
61pub struct Cell<T> {
62    val: MaybeUninit<T>,
63    state: AtomicMemoryRefer,
64}
65impl<T> Cell<T> {
66    pub const fn new() -> Self {
67        Cell {
68            val: MaybeUninit::uninit(),
69            state: AtomicMemoryRefer::new(MemoryRefer::new()),
70        }
71    }
72    pub const fn new_with(init: T) -> Self {
73        Cell {
74            val: MaybeUninit::new(init),
75            state: AtomicMemoryRefer::new(MemoryRefer::new()),
76        }
77    }
78    fn ptr(&self) -> *mut T {
79        self.val.as_ptr() as *mut T
80    }
81    pub fn is_initialized(&self) -> bool {
82        let state = self.state.load(SeqCst);
83        state.state().is_initialized()
84    }
85    pub fn ref_num(&self) -> Result<usize, MemoryState> {
86        self.state.load(SeqCst).ref_num()
87    }
88
89    pub fn try_take(&self) -> Result<Option<T>, Error<()>> {
93        let _cs = CriticalSection::new();
94        let refer = match self.state.fetch_update(SeqCst, Relaxed, |mut x| {
95            let state = x.state();
96            if state.is_initialized() || state.is_regaining() {
97                if x.ref_num() == Ok(0) {
98                    x.set_state(MemoryState::Erasing);
99                } else {
100                    x.set_state(MemoryState::Regaining);
101                }
102                Some(x)
103            } else {
104                None
105            }
106        }) {
107            Ok(v) => v,
108            Err(v) => v,
109        };
110
111        match refer.state() {
112            MemoryState::Uninitialized => Ok(None),
113            MemoryState::Initialized | MemoryState::Regaining => {
114                if refer.ref_num() == Ok(0) {
115                    let ret = unsafe { ptr::read(self.ptr()) };
116                    self.state.store(MemoryState::Uninitialized.into(), SeqCst);
117                    Ok(Some(ret))
118                } else {
119                    Err(Error {
120                        state: MemoryState::Regaining,
121                        input: (),
122                        retry: true,
123                    })
124                }
125            }
126            state => Err(Error {
127                state,
128                input: (),
129                retry: state.is_transient(),
130            }),
131        }
132    }
133    pub fn take(&self) -> Result<Option<T>, Error<()>> {
139        retry(|_| self.try_take(), ())
140    }
141
142    pub unsafe fn peek(&self) -> &T {
143        self.val.assume_init_ref()
144    }
145    pub fn try_get(&self) -> Result<Ref<T>, Error<()>> {
149        if let Err(state) = self.state.fetch_update(SeqCst, Relaxed, |mut x| {
150            if x.ref_add().is_ok() {
151                Some(x)
152            } else {
153                None
154            }
155        }) {
156            let state = state.state();
157            Err(Error {
158                state,
159                input: (),
160                retry: state.is_initializing(),
161            })
162        } else {
163            Ok(Ref(self))
164        }
165    }
166    pub fn get(&self) -> Result<Ref<T>, Error<()>> {
172        retry(|_| self.try_get(), ())
173    }
174
175    pub fn try_set(&self, value: T) -> Result<(), Error<T>> {
179        let _cs = CriticalSection::new();
180        if let Err(state) = self.state.compare_exchange(
181            MemoryState::Uninitialized.into(),
182            MemoryState::Initializing.into(),
183            SeqCst,
184            SeqCst,
185        ) {
186            let state = state.state();
187            Err(Error {
188                state,
189                input: value,
190                retry: state.is_erasing(),
191            })
192        } else {
193            unsafe { ptr::write(self.ptr(), value) };
194            self.state.store(MemoryState::Initialized.into(), SeqCst);
195            Ok(())
196        }
197    }
198    pub fn set(&self, value: T) -> Result<(), Error<T>> {
204        retry(|v| self.try_set(v), value)
205    }
206
207    pub fn try_replace(&self, value: T) -> Result<Option<T>, Error<T>> {
211        let _cs = CriticalSection::new();
212        let refer = match self.state.fetch_update(SeqCst, Relaxed, |mut x| {
213            let state = x.state();
214            if state.is_initialized() || state.is_regaining() {
215                if x.ref_num() == Ok(0) {
216                    x.set_state(MemoryState::Initializing);
217                } else {
218                    x.set_state(MemoryState::Regaining);
219                }
220                Some(x)
221            } else if state.is_uninitialized() {
222                x.set_state(MemoryState::Initializing);
223                Some(x)
224            } else {
225                None
226            }
227        }) {
228            Ok(v) => v,
229            Err(v) => v,
230        };
231
232        match refer.state() {
233            MemoryState::Uninitialized => {
234                unsafe { ptr::write(self.ptr(), value) };
235                self.state.store(MemoryState::Initialized.into(), SeqCst);
236                Ok(None)
237            }
238            MemoryState::Initialized | MemoryState::Regaining => {
239                if refer.ref_num() == Ok(0) {
240                    let ret = unsafe { ptr::read(self.ptr()) };
241                    unsafe { ptr::write(self.ptr(), value) };
242                    self.state.store(MemoryState::Initialized.into(), SeqCst);
243                    Ok(Some(ret))
244                } else {
245                    Err(Error {
246                        state: MemoryState::Regaining,
247                        input: value,
248                        retry: true,
249                    })
250                }
251            }
252            state => Err(Error {
253                state,
254                input: value,
255                retry: state.is_transient(),
256            }),
257        }
258    }
259    pub fn replace(&self, value: T) -> Result<Option<T>, Error<T>> {
265        retry(|v| self.try_replace(v), value)
266    }
267
268    pub fn get_or_try_init(&self, value: T) -> Result<Ref<T>, Error<T>> {
272        let ret = self.try_set(value);
273        if let Ok(v) = self.try_get() {
274            Ok(v)
275        } else {
276            Err(ret.unwrap_err())
277        }
278    }
279    pub fn get_or_init(&self, value: T) -> Ref<T> {
283        retry(|v| self.get_or_try_init(v), value).unwrap()
284    }
285}
286impl<'a, T: fmt::Debug> fmt::Debug for Cell<T> {
287    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
288        let v = if let Ok(v) = self.try_get() {
289            Some(v)
290        } else {
291            None
292        };
293        fmt::Debug::fmt(&v, f)
294    }
295}
296impl<T> Drop for Cell<T> {
297    fn drop(&mut self) {
298        let _ = self.take();
299    }
300}