embedded_async_helpers/
ssq.rs1use atomic_polyfill::{AtomicBool, Ordering};
6use core::{cell::UnsafeCell, mem::MaybeUninit, ptr, task::Waker};
7
8pub type WakerQueue = SingleSlotQueue<Waker>;
10
11pub type WakerConsumer = Consumer<'static, Waker>;
13
14pub type WakerProducer = Consumer<'static, Waker>;
16
17pub struct SingleSlotQueue<T> {
19 full: AtomicBool,
20 val: UnsafeCell<MaybeUninit<T>>,
21}
22
23impl<T> SingleSlotQueue<T> {
24 pub const fn new() -> Self {
26 SingleSlotQueue {
27 full: AtomicBool::new(false),
28 val: UnsafeCell::new(MaybeUninit::uninit()),
29 }
30 }
31
32 pub fn split<'a>(&'a mut self) -> (Consumer<'a, T>, Producer<'a, T>) {
34 (Consumer { ssq: self }, Producer { ssq: self })
35 }
36}
37
38impl<T> Drop for SingleSlotQueue<T> {
39 fn drop(&mut self) {
40 if self.full.load(Ordering::Relaxed) {
41 unsafe {
42 ptr::drop_in_place(self.val.get() as *mut T);
43 }
44 }
45 }
46}
47
48pub struct Consumer<'a, T> {
50 ssq: &'a SingleSlotQueue<T>,
51}
52
53impl<'a, T> Consumer<'a, T> {
54 #[inline]
56 pub fn dequeue(&mut self) -> Option<T> {
57 if self.ssq.full.load(Ordering::Acquire) {
58 let r = Some(unsafe { ptr::read(self.ssq.val.get().cast()) });
59 self.ssq.full.store(false, Ordering::Release);
60 r
61 } else {
62 None
63 }
64 }
65
66 #[inline]
68 pub fn is_empty(&self) -> bool {
69 !self.ssq.full.load(Ordering::Relaxed)
70 }
71}
72
73unsafe impl<'a, T> Send for Consumer<'a, T> {}
75
76pub struct Producer<'a, T> {
78 ssq: &'a SingleSlotQueue<T>,
79}
80
81impl<'a, T> Producer<'a, T> {
82 #[inline]
85 pub fn enqueue(&mut self, val: T) -> Option<T> {
86 if !self.ssq.full.load(Ordering::Acquire) {
87 unsafe { ptr::write(self.ssq.val.get().cast(), val) };
88 self.ssq.full.store(true, Ordering::Release);
89 None
90 } else {
91 Some(val)
92 }
93 }
94
95 #[inline]
97 pub fn is_empty(&self) -> bool {
98 !self.ssq.full.load(Ordering::Relaxed)
99 }
100}
101
102unsafe impl<'a, T> Send for Producer<'a, T> {}