aboutsummaryrefslogtreecommitdiff
path: root/embassy-sync/src
diff options
context:
space:
mode:
authorivmarkov <[email protected]>2022-09-22 09:05:40 +0300
committerivmarkov <[email protected]>2022-09-24 20:26:51 +0300
commitca92302d038e3a8f1446085040228bac7a1d00e6 (patch)
treec4d3dd0f43c164da68603f4ee31dc7ed7ecc204c /embassy-sync/src
parenteeb1515e9fd093e4a9797abac25ca657e1e35dc3 (diff)
Parameterize Signal with RawMutex
Diffstat (limited to 'embassy-sync/src')
-rw-r--r--embassy-sync/src/signal.rs69
1 files changed, 41 insertions, 28 deletions
diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs
index b4d99513a..7c38637c3 100644
--- a/embassy-sync/src/signal.rs
+++ b/embassy-sync/src/signal.rs
@@ -1,9 +1,12 @@
1//! A synchronization primitive for passing the latest value to a task. 1//! A synchronization primitive for passing the latest value to a task.
2use core::cell::UnsafeCell; 2use core::cell::Cell;
3use core::future::{poll_fn, Future}; 3use core::future::{poll_fn, Future};
4use core::mem; 4use core::mem;
5use core::task::{Context, Poll, Waker}; 5use core::task::{Context, Poll, Waker};
6 6
7use crate::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex};
8use crate::blocking_mutex::Mutex;
9
7/// Single-slot signaling primitive. 10/// Single-slot signaling primitive.
8/// 11///
9/// This is similar to a [`Channel`](crate::channel::Channel) with a buffer size of 1, except 12/// This is similar to a [`Channel`](crate::channel::Channel) with a buffer size of 1, except
@@ -28,8 +31,11 @@ use core::task::{Context, Poll, Waker};
28/// 31///
29/// static SOME_SIGNAL: Signal<SomeCommand> = Signal::new(); 32/// static SOME_SIGNAL: Signal<SomeCommand> = Signal::new();
30/// ``` 33/// ```
31pub struct Signal<T> { 34pub struct Signal<T, R = CriticalSectionRawMutex>
32 state: UnsafeCell<State<T>>, 35where
36 R: RawMutex,
37{
38 state: Mutex<R, Cell<State<T>>>,
33} 39}
34 40
35enum State<T> { 41enum State<T> {
@@ -38,24 +44,27 @@ enum State<T> {
38 Signaled(T), 44 Signaled(T),
39} 45}
40 46
41unsafe impl<T: Send> Send for Signal<T> {} 47impl<T, R> Signal<T, R>
42unsafe impl<T: Send> Sync for Signal<T> {} 48where
43 49 R: RawMutex,
44impl<T> Signal<T> { 50{
45 /// Create a new `Signal`. 51 /// Create a new `Signal`.
46 pub const fn new() -> Self { 52 pub const fn new() -> Self {
47 Self { 53 Self {
48 state: UnsafeCell::new(State::None), 54 state: Mutex::new(Cell::new(State::None)),
49 } 55 }
50 } 56 }
51} 57}
52 58
53impl<T: Send> Signal<T> { 59impl<R, T: Send> Signal<T, R>
60where
61 R: RawMutex,
62{
54 /// Mark this Signal as signaled. 63 /// Mark this Signal as signaled.
55 pub fn signal(&self, val: T) { 64 pub fn signal(&self, val: T) {
56 critical_section::with(|_| unsafe { 65 self.state.lock(|cell| {
57 let state = &mut *self.state.get(); 66 let state = cell.replace(State::Signaled(val));
58 if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) { 67 if let State::Waiting(waker) = state {
59 waker.wake(); 68 waker.wake();
60 } 69 }
61 }) 70 })
@@ -63,31 +72,27 @@ impl<T: Send> Signal<T> {
63 72
64 /// Remove the queued value in this `Signal`, if any. 73 /// Remove the queued value in this `Signal`, if any.
65 pub fn reset(&self) { 74 pub fn reset(&self) {
66 critical_section::with(|_| unsafe { 75 self.state.lock(|cell| cell.set(State::None));
67 let state = &mut *self.state.get();
68 *state = State::None
69 })
70 } 76 }
71 77
72 /// Manually poll the Signal future. 78 fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> {
73 pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { 79 self.state.lock(|cell| {
74 critical_section::with(|_| unsafe { 80 let state = cell.replace(State::None);
75 let state = &mut *self.state.get();
76 match state { 81 match state {
77 State::None => { 82 State::None => {
78 *state = State::Waiting(cx.waker().clone()); 83 cell.set(State::Waiting(cx.waker().clone()));
84 Poll::Pending
85 }
86 State::Waiting(w) if w.will_wake(cx.waker()) => {
87 cell.set(State::Waiting(w));
79 Poll::Pending 88 Poll::Pending
80 } 89 }
81 State::Waiting(w) if w.will_wake(cx.waker()) => Poll::Pending,
82 State::Waiting(w) => { 90 State::Waiting(w) => {
83 let w = mem::replace(w, cx.waker().clone()); 91 cell.set(State::Waiting(cx.waker().clone()));
84 w.wake(); 92 w.wake();
85 Poll::Pending 93 Poll::Pending
86 } 94 }
87 State::Signaled(_) => match mem::replace(state, State::None) { 95 State::Signaled(res) => Poll::Ready(res),
88 State::Signaled(res) => Poll::Ready(res),
89 _ => unreachable!(),
90 },
91 } 96 }
92 }) 97 })
93 } 98 }
@@ -99,6 +104,14 @@ impl<T: Send> Signal<T> {
99 104
100 /// non-blocking method to check whether this signal has been signaled. 105 /// non-blocking method to check whether this signal has been signaled.
101 pub fn signaled(&self) -> bool { 106 pub fn signaled(&self) -> bool {
102 critical_section::with(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) 107 self.state.lock(|cell| {
108 let state = cell.replace(State::None);
109
110 let res = matches!(state, State::Signaled(_));
111
112 cell.set(state);
113
114 res
115 })
103 } 116 }
104} 117}