aboutsummaryrefslogtreecommitdiff
path: root/embassy-sync/src/waitqueue/atomic_waker.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-sync/src/waitqueue/atomic_waker.rs')
-rw-r--r--embassy-sync/src/waitqueue/atomic_waker.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/embassy-sync/src/waitqueue/atomic_waker.rs b/embassy-sync/src/waitqueue/atomic_waker.rs
new file mode 100644
index 000000000..63fe04a6e
--- /dev/null
+++ b/embassy-sync/src/waitqueue/atomic_waker.rs
@@ -0,0 +1,41 @@
1use core::cell::Cell;
2use core::task::Waker;
3
4use crate::blocking_mutex::raw::CriticalSectionRawMutex;
5use crate::blocking_mutex::Mutex;
6
7/// Utility struct to register and wake a waker.
8pub struct AtomicWaker {
9 waker: Mutex<CriticalSectionRawMutex, Cell<Option<Waker>>>,
10}
11
12impl AtomicWaker {
13 /// Create a new `AtomicWaker`.
14 pub const fn new() -> Self {
15 Self {
16 waker: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),
17 }
18 }
19
20 /// Register a waker. Overwrites the previous waker, if any.
21 pub fn register(&self, w: &Waker) {
22 critical_section::with(|cs| {
23 let cell = self.waker.borrow(cs);
24 cell.set(match cell.replace(None) {
25 Some(w2) if (w2.will_wake(w)) => Some(w2),
26 _ => Some(w.clone()),
27 })
28 })
29 }
30
31 /// Wake the registered waker, if any.
32 pub fn wake(&self) {
33 critical_section::with(|cs| {
34 let cell = self.waker.borrow(cs);
35 if let Some(w) = cell.replace(None) {
36 w.wake_by_ref();
37 cell.set(Some(w));
38 }
39 })
40 }
41}