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}