postage/sync/
oneshot_cell.rs1use atomic::Ordering;
2
3use super::state_cell::StateCell;
4
5#[derive(Copy, Clone)]
6enum State {
7 None,
8 Writing,
9 Ready,
10 Taken,
11}
12
13pub enum TryRecvError {
14 Pending,
15 Closed,
16}
17
18pub struct OneshotCell<T> {
19 state: StateCell<State, T>,
20}
21
22impl<T> OneshotCell<T> {
23 pub fn new() -> Self {
24 Self {
25 state: StateCell::new(State::None),
26 }
27 }
28
29 pub fn send(&self, value: T) -> Result<(), T> {
30 unsafe {
31 self.state
32 .compare_store(
33 State::None,
34 State::Writing,
35 value,
36 State::Ready,
37 Ordering::AcqRel,
38 Ordering::Relaxed,
39 )
40 .map_err(|err| err.1)?;
41 }
42
43 Ok(())
44 }
45
46 pub fn try_recv(&self) -> Result<T, TryRecvError> {
47 unsafe {
48 match self.state.compare_take(
49 State::Ready,
50 State::Taken,
51 Ordering::AcqRel,
52 Ordering::Relaxed,
53 ) {
54 Ok(v) => Ok(v),
55 Err(e) => match e {
56 State::None => Err(TryRecvError::Pending),
57 State::Writing => Err(TryRecvError::Pending),
58 State::Ready => unreachable!(),
59 State::Taken => Err(TryRecvError::Closed),
60 },
61 }
62 }
63 }
64}