postage/sync/
state_cell.rs

1use 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}