spsc_ringbuf_core/
shared_singleton.rs1
2#![allow(dead_code)]
3use core::{cell::Cell, cell::UnsafeCell};
4use core::mem::MaybeUninit;
5use core::marker::Sync;
6
7#[derive(Debug)]
8pub enum ErrCode {
9 NotOwned
10}
11
12#[derive(Copy, Clone, PartialEq)]
13enum Owner {
14 Vacant, Producer, Consumer, }
18
19pub struct SharedSingleton <T> {
29 owner: Cell<Owner>,
31 ucell: UnsafeCell<MaybeUninit<T>>,
32}
33
34unsafe impl <T> Sync for SharedSingleton<T> {}
37
38impl <T> SharedSingleton<T> {
39
40 const INIT_U: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit());
41 pub const INIT_0: SharedSingleton<T> = Self::new();
42
43 #[inline]
44 pub const fn new() -> Self {
45 SharedSingleton { owner: Cell::new(Owner::Vacant), ucell: Self::INIT_U }
46 }
47
48 #[inline]
49 pub fn is_vacant(&self) -> bool {
50 self.owner.get() == Owner::Vacant
51 }
52
53 #[inline]
55 pub fn try_write(&self) -> Option<&mut T> {
56 if self.owner.get() == Owner::Vacant {
57 let x: *mut MaybeUninit<T> = self.ucell.get();
58 let t: &mut T = unsafe { &mut *(x as *mut T)};
59 self.owner.set(Owner::Producer);
60 Some(t)
61 }
62 else {
63 None
64 }
65 }
66
67 #[inline]
69 pub fn write_done(&self) -> Result<(),ErrCode> {
70 if self.owner.get() == Owner::Producer {
71 self.owner.set(Owner::Consumer);
72 Ok(())
73 }
74 else {
75 Err(ErrCode::NotOwned)
76 }
77 }
78
79 #[inline]
83 pub fn try_read(&self) -> Option<&T> {
84 if self.owner.get() == Owner::Consumer {
85 let x: *mut MaybeUninit<T> = self.ucell.get();
86 let t: & T = unsafe { & *(x as * const T)};
87 Some(t)
88 }
89 else {
90 None
91 }
92 }
93
94 #[inline]
96 pub fn read_done(&self) -> Result<(),ErrCode> {
97 if self.owner.get() == Owner::Consumer {
98 self.owner.set(Owner::Vacant);
99 Ok(())
100 }
101 else {
102 Err(ErrCode::NotOwned)
103 }
104 }
105}
106
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 pub struct SomeStruct {
113 id: u32,
114 }
115
116 #[test]
117 fn ownership_changes() {
118
119 let shared = SharedSingleton::<SomeStruct>::new();
120
121 if let Some(payload) = shared.try_write() {
122
123 assert!(shared.try_write().is_none());
125
126 payload.id = 42;
127 assert!(shared.write_done().is_ok());
128 }
129
130 assert!(shared.try_write().is_none());
132
133 assert!(shared.try_read().is_some());
134
135 assert!(shared.try_read().unwrap().id == 42);
136
137 assert!(shared.read_done().is_ok());
138
139 }
140
141}