postage/sync/
state_cell.rs1use std::cell::UnsafeCell;
2
3use atomic::{Atomic, Ordering};
4
5pub struct StateCell<S, T>
6where
7 S: Copy,
8{
9 state: Atomic<S>,
10 data: UnsafeCell<Option<T>>,
11}
12
13impl<S, T> StateCell<S, T>
14where
15 S: Copy,
16{
17 pub fn new(state: S) -> Self {
18 debug_assert!(Atomic::<S>::is_lock_free());
19
20 Self {
21 state: Atomic::new(state),
22 data: UnsafeCell::new(None),
23 }
24 }
25
26 pub unsafe fn compare_store(
27 &self,
28 current: S,
29 locked: S,
30 data: T,
31 complete: S,
32 success: Ordering,
33 failure: Ordering,
34 ) -> Result<S, (S, T)> {
35 match self
36 .state
37 .compare_exchange(current, locked, success, failure)
38 {
39 Ok(s) => {
40 *self.data.get() = Some(data);
41 self.state.store(complete, Ordering::Release);
42 Ok(s)
43 }
44 Err(s) => Err((s, data)),
45 }
46 }
47
48 pub unsafe fn compare_take(
49 &self,
50 current: S,
51 new: S,
52 success: Ordering,
53 failure: Ordering,
54 ) -> Result<T, S> {
55 match self.state.compare_exchange(current, new, success, failure) {
56 Ok(_s) => Ok(self.take_internal()),
57 Err(s) => Err(s),
58 }
59 }
60
61 unsafe fn take_internal(&self) -> T {
62 let reference = self.data.get().as_mut().unwrap();
63 reference.take().unwrap()
64 }
65}
66
67unsafe impl<S, T> Sync for StateCell<S, T>
68where
69 S: Copy,
70 T: Send,
71{
72}