1 | //! A synchronization primitive for passing the latest value to a task. |
2 | use core::cell::Cell; |
3 | use core::future::{poll_fn, Future}; |
4 | use core::task::{Context, Poll, Waker}; |
5 | |
6 | use crate::blocking_mutex::raw::RawMutex; |
7 | use crate::blocking_mutex::Mutex; |
8 | |
9 | /// Single-slot signaling primitive. |
10 | /// |
11 | /// This is similar to a [`Channel`](crate::channel::Channel) with a buffer size of 1, except |
12 | /// "sending" to it (calling [`Signal::signal`]) when full will overwrite the previous value instead |
13 | /// of waiting for the receiver to pop the previous value. |
14 | /// |
15 | /// It is useful for sending data between tasks when the receiver only cares about |
16 | /// the latest data, and therefore it's fine to "lose" messages. This is often the case for "state" |
17 | /// updates. |
18 | /// |
19 | /// For more advanced use cases, you might want to use [`Channel`](crate::channel::Channel) instead. |
20 | /// |
21 | /// Signals are generally declared as `static`s and then borrowed as required. |
22 | /// |
23 | /// ``` |
24 | /// use embassy_sync::signal::Signal; |
25 | /// use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
26 | /// |
27 | /// enum SomeCommand { |
28 | /// On, |
29 | /// Off, |
30 | /// } |
31 | /// |
32 | /// static SOME_SIGNAL: Signal<CriticalSectionRawMutex, SomeCommand> = Signal::new(); |
33 | /// ``` |
34 | pub struct Signal<M, T> |
35 | where |
36 | M: RawMutex, |
37 | { |
38 | state: Mutex<M, Cell<State<T>>>, |
39 | } |
40 | |
41 | enum State<T> { |
42 | None, |
43 | Waiting(Waker), |
44 | Signaled(T), |
45 | } |
46 | |
47 | impl<M, T> Signal<M, T> |
48 | where |
49 | M: RawMutex, |
50 | { |
51 | /// Create a new `Signal`. |
52 | pub const fn new() -> Self { |
53 | Self { |
54 | state: Mutex::new(val:Cell::new(State::None)), |
55 | } |
56 | } |
57 | } |
58 | |
59 | impl<M, T> Default for Signal<M, T> |
60 | where |
61 | M: RawMutex, |
62 | { |
63 | fn default() -> Self { |
64 | Self::new() |
65 | } |
66 | } |
67 | |
68 | impl<M, T> Signal<M, T> |
69 | where |
70 | M: RawMutex, |
71 | { |
72 | /// Mark this Signal as signaled. |
73 | pub fn signal(&self, val: T) { |
74 | self.state.lock(|cell| { |
75 | let state = cell.replace(State::Signaled(val)); |
76 | if let State::Waiting(waker) = state { |
77 | waker.wake(); |
78 | } |
79 | }) |
80 | } |
81 | |
82 | /// Remove the queued value in this `Signal`, if any. |
83 | pub fn reset(&self) { |
84 | self.state.lock(|cell| cell.set(State::None)); |
85 | } |
86 | |
87 | fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { |
88 | self.state.lock(|cell| { |
89 | let state = cell.replace(State::None); |
90 | match state { |
91 | State::None => { |
92 | cell.set(State::Waiting(cx.waker().clone())); |
93 | Poll::Pending |
94 | } |
95 | State::Waiting(w) if w.will_wake(cx.waker()) => { |
96 | cell.set(State::Waiting(w)); |
97 | Poll::Pending |
98 | } |
99 | State::Waiting(w) => { |
100 | cell.set(State::Waiting(cx.waker().clone())); |
101 | w.wake(); |
102 | Poll::Pending |
103 | } |
104 | State::Signaled(res) => Poll::Ready(res), |
105 | } |
106 | }) |
107 | } |
108 | |
109 | /// Future that completes when this Signal has been signaled. |
110 | pub fn wait(&self) -> impl Future<Output = T> + '_ { |
111 | poll_fn(move |cx| self.poll_wait(cx)) |
112 | } |
113 | |
114 | /// non-blocking method to try and take the signal value. |
115 | pub fn try_take(&self) -> Option<T> { |
116 | self.state.lock(|cell| { |
117 | let state = cell.replace(State::None); |
118 | match state { |
119 | State::Signaled(res) => Some(res), |
120 | state => { |
121 | cell.set(state); |
122 | None |
123 | } |
124 | } |
125 | }) |
126 | } |
127 | |
128 | /// non-blocking method to check whether this signal has been signaled. This does not clear the signal. |
129 | pub fn signaled(&self) -> bool { |
130 | self.state.lock(|cell| { |
131 | let state = cell.replace(State::None); |
132 | |
133 | let res = matches!(state, State::Signaled(_)); |
134 | |
135 | cell.set(state); |
136 | |
137 | res |
138 | }) |
139 | } |
140 | } |
141 | |