aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-06-26 01:09:53 +0200
committerGitHub <[email protected]>2022-06-26 01:09:53 +0200
commitc460af62e0648850484368d5d4984ddf9a2ade7a (patch)
treedb4f05d94d8aaf72c3ece937e5e3f39aa32acd74
parent29cdb91b138416a31db270cbe96483bf7c09eb81 (diff)
parent5903e08f4b3e5cdf61a80a5dd658104ab03dd4aa (diff)
Merge pull request #835 from embassy-rs/fixes
Misc API and doc fixes.
-rw-r--r--embassy/src/blocking_mutex/mod.rs9
-rw-r--r--embassy/src/blocking_mutex/raw.rs37
-rw-r--r--embassy/src/channel/mpmc.rs4
-rw-r--r--embassy/src/channel/pubsub/mod.rs8
-rw-r--r--embassy/src/channel/signal.rs22
-rw-r--r--embassy/src/executor/raw/mod.rs4
-rw-r--r--embassy/src/executor/raw/waker.rs12
-rw-r--r--embassy/src/executor/spawner.rs4
-rw-r--r--embassy/src/lib.rs1
-rw-r--r--embassy/src/util/forever.rs31
-rw-r--r--embassy/src/util/select.rs12
-rw-r--r--embassy/src/waitqueue/waker.rs6
-rw-r--r--embassy/src/waitqueue/waker_agnostic.rs2
13 files changed, 123 insertions, 29 deletions
diff --git a/embassy/src/blocking_mutex/mod.rs b/embassy/src/blocking_mutex/mod.rs
index 602ec8a07..c9db89f01 100644
--- a/embassy/src/blocking_mutex/mod.rs
+++ b/embassy/src/blocking_mutex/mod.rs
@@ -160,11 +160,20 @@ mod thread_mode_mutex {
160 } 160 }
161 161
162 impl<T: ?Sized> ThreadModeMutex<T> { 162 impl<T: ?Sized> ThreadModeMutex<T> {
163 /// Lock the `ThreadModeMutex`, granting access to the data.
164 ///
165 /// # Panics
166 ///
167 /// This will panic if not currently running in thread mode.
163 pub fn lock<R>(&self, f: impl FnOnce(&T) -> R) -> R { 168 pub fn lock<R>(&self, f: impl FnOnce(&T) -> R) -> R {
164 f(self.borrow()) 169 f(self.borrow())
165 } 170 }
166 171
167 /// Borrows the data 172 /// Borrows the data
173 ///
174 /// # Panics
175 ///
176 /// This will panic if not currently running in thread mode.
168 pub fn borrow(&self) -> &T { 177 pub fn borrow(&self) -> &T {
169 assert!( 178 assert!(
170 raw::in_thread_mode(), 179 raw::in_thread_mode(),
diff --git a/embassy/src/blocking_mutex/raw.rs b/embassy/src/blocking_mutex/raw.rs
index bdb443e4d..669a23e31 100644
--- a/embassy/src/blocking_mutex/raw.rs
+++ b/embassy/src/blocking_mutex/raw.rs
@@ -3,12 +3,32 @@
3//! This module provides a trait for mutexes that can be used in different contexts. 3//! This module provides a trait for mutexes that can be used in different contexts.
4use core::marker::PhantomData; 4use core::marker::PhantomData;
5 5
6/// Any object implementing this trait guarantees exclusive access to the data contained 6/// Raw mutex trait.
7/// within the mutex for the duration of the lock. 7///
8/// Adapted from <https://github.com/rust-embedded/mutex-trait>. 8/// This mutex is "raw", which means it does not actually contain the protected data, it
9pub trait RawMutex { 9/// just implements the mutex mechanism. For most uses you should use [`super::Mutex`] instead,
10/// which is generic over a RawMutex and contains the protected data.
11///
12/// Note that, unlike other mutexes, implementations only guarantee no
13/// concurrent access from other threads: concurrent access from the current
14/// thread is allwed. For example, it's possible to lock the same mutex multiple times reentrantly.
15///
16/// Therefore, locking a `RawMutex` is only enough to guarantee safe shared (`&`) access
17/// to the data, it is not enough to guarantee exclusive (`&mut`) access.
18///
19/// # Safety
20///
21/// RawMutex implementations must ensure that, while locked, no other thread can lock
22/// the RawMutex concurrently.
23///
24/// Unsafe code is allowed to rely on this fact, so incorrect implementations will cause undefined behavior.
25pub unsafe trait RawMutex {
26 /// Create a new `RawMutex` instance.
27 ///
28 /// This is a const instead of a method to allow creating instances in const context.
10 const INIT: Self; 29 const INIT: Self;
11 30
31 /// Lock this `RawMutex`.
12 fn lock<R>(&self, f: impl FnOnce() -> R) -> R; 32 fn lock<R>(&self, f: impl FnOnce() -> R) -> R;
13} 33}
14 34
@@ -24,12 +44,13 @@ unsafe impl Send for CriticalSectionRawMutex {}
24unsafe impl Sync for CriticalSectionRawMutex {} 44unsafe impl Sync for CriticalSectionRawMutex {}
25 45
26impl CriticalSectionRawMutex { 46impl CriticalSectionRawMutex {
47 /// Create a new `CriticalSectionRawMutex`.
27 pub const fn new() -> Self { 48 pub const fn new() -> Self {
28 Self { _phantom: PhantomData } 49 Self { _phantom: PhantomData }
29 } 50 }
30} 51}
31 52
32impl RawMutex for CriticalSectionRawMutex { 53unsafe impl RawMutex for CriticalSectionRawMutex {
33 const INIT: Self = Self::new(); 54 const INIT: Self = Self::new();
34 55
35 fn lock<R>(&self, f: impl FnOnce() -> R) -> R { 56 fn lock<R>(&self, f: impl FnOnce() -> R) -> R {
@@ -51,12 +72,13 @@ pub struct NoopRawMutex {
51unsafe impl Send for NoopRawMutex {} 72unsafe impl Send for NoopRawMutex {}
52 73
53impl NoopRawMutex { 74impl NoopRawMutex {
75 /// Create a new `NoopRawMutex`.
54 pub const fn new() -> Self { 76 pub const fn new() -> Self {
55 Self { _phantom: PhantomData } 77 Self { _phantom: PhantomData }
56 } 78 }
57} 79}
58 80
59impl RawMutex for NoopRawMutex { 81unsafe impl RawMutex for NoopRawMutex {
60 const INIT: Self = Self::new(); 82 const INIT: Self = Self::new();
61 fn lock<R>(&self, f: impl FnOnce() -> R) -> R { 83 fn lock<R>(&self, f: impl FnOnce() -> R) -> R {
62 f() 84 f()
@@ -84,12 +106,13 @@ mod thread_mode {
84 unsafe impl Sync for ThreadModeRawMutex {} 106 unsafe impl Sync for ThreadModeRawMutex {}
85 107
86 impl ThreadModeRawMutex { 108 impl ThreadModeRawMutex {
109 /// Create a new `ThreadModeRawMutex`.
87 pub const fn new() -> Self { 110 pub const fn new() -> Self {
88 Self { _phantom: PhantomData } 111 Self { _phantom: PhantomData }
89 } 112 }
90 } 113 }
91 114
92 impl RawMutex for ThreadModeRawMutex { 115 unsafe impl RawMutex for ThreadModeRawMutex {
93 const INIT: Self = Self::new(); 116 const INIT: Self = Self::new();
94 fn lock<R>(&self, f: impl FnOnce() -> R) -> R { 117 fn lock<R>(&self, f: impl FnOnce() -> R) -> R {
95 assert!(in_thread_mode(), "ThreadModeMutex can only be locked from thread mode."); 118 assert!(in_thread_mode(), "ThreadModeMutex can only be locked from thread mode.");
diff --git a/embassy/src/channel/mpmc.rs b/embassy/src/channel/mpmc.rs
index 1d03eef19..ca2214bb5 100644
--- a/embassy/src/channel/mpmc.rs
+++ b/embassy/src/channel/mpmc.rs
@@ -180,6 +180,7 @@ where
180 } 180 }
181} 181}
182 182
183/// Future returned by [`Channel::recv`] and [`Receiver::recv`].
183pub struct RecvFuture<'ch, M, T, const N: usize> 184pub struct RecvFuture<'ch, M, T, const N: usize>
184where 185where
185 M: RawMutex, 186 M: RawMutex,
@@ -201,6 +202,7 @@ where
201 } 202 }
202} 203}
203 204
205/// Future returned by [`DynamicReceiver::recv`].
204pub struct DynamicRecvFuture<'ch, T> { 206pub struct DynamicRecvFuture<'ch, T> {
205 channel: &'ch dyn DynamicChannel<T>, 207 channel: &'ch dyn DynamicChannel<T>,
206} 208}
@@ -216,6 +218,7 @@ impl<'ch, T> Future for DynamicRecvFuture<'ch, T> {
216 } 218 }
217} 219}
218 220
221/// Future returned by [`Channel::send`] and [`Sender::send`].
219pub struct SendFuture<'ch, M, T, const N: usize> 222pub struct SendFuture<'ch, M, T, const N: usize>
220where 223where
221 M: RawMutex, 224 M: RawMutex,
@@ -246,6 +249,7 @@ where
246 249
247impl<'ch, M, T, const N: usize> Unpin for SendFuture<'ch, M, T, N> where M: RawMutex {} 250impl<'ch, M, T, const N: usize> Unpin for SendFuture<'ch, M, T, N> where M: RawMutex {}
248 251
252/// Future returned by [`DynamicSender::send`].
249pub struct DynamicSendFuture<'ch, T> { 253pub struct DynamicSendFuture<'ch, T> {
250 channel: &'ch dyn DynamicChannel<T>, 254 channel: &'ch dyn DynamicChannel<T>,
251 message: Option<T>, 255 message: Option<T>,
diff --git a/embassy/src/channel/pubsub/mod.rs b/embassy/src/channel/pubsub/mod.rs
index 11c889368..64a72a52c 100644
--- a/embassy/src/channel/pubsub/mod.rs
+++ b/embassy/src/channel/pubsub/mod.rs
@@ -104,7 +104,7 @@ impl<M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usi
104 /// Create a new subscriber. It will only receive messages that are published after its creation. 104 /// Create a new subscriber. It will only receive messages that are published after its creation.
105 /// 105 ///
106 /// If there are no subscriber slots left, an error will be returned. 106 /// If there are no subscriber slots left, an error will be returned.
107 pub fn dyn_subscriber<'a>(&'a self) -> Result<DynSubscriber<'a, T>, Error> { 107 pub fn dyn_subscriber(&self) -> Result<DynSubscriber<'_, T>, Error> {
108 self.inner.lock(|inner| { 108 self.inner.lock(|inner| {
109 let mut s = inner.borrow_mut(); 109 let mut s = inner.borrow_mut();
110 110
@@ -136,7 +136,7 @@ impl<M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usi
136 /// Create a new publisher 136 /// Create a new publisher
137 /// 137 ///
138 /// If there are no publisher slots left, an error will be returned. 138 /// If there are no publisher slots left, an error will be returned.
139 pub fn dyn_publisher<'a>(&'a self) -> Result<DynPublisher<'a, T>, Error> { 139 pub fn dyn_publisher(&self) -> Result<DynPublisher<'_, T>, Error> {
140 self.inner.lock(|inner| { 140 self.inner.lock(|inner| {
141 let mut s = inner.borrow_mut(); 141 let mut s = inner.borrow_mut();
142 142
@@ -369,7 +369,7 @@ impl<T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize> PubSubSta
369} 369}
370 370
371/// Error type for the [PubSubChannel] 371/// Error type for the [PubSubChannel]
372#[derive(Debug, PartialEq, Clone)] 372#[derive(Debug, PartialEq, Eq, Clone)]
373#[cfg_attr(feature = "defmt", derive(defmt::Format))] 373#[cfg_attr(feature = "defmt", derive(defmt::Format))]
374pub enum Error { 374pub enum Error {
375 /// All subscriber slots are used. To add another subscriber, first another subscriber must be dropped or 375 /// All subscriber slots are used. To add another subscriber, first another subscriber must be dropped or
@@ -404,7 +404,7 @@ pub trait PubSubBehavior<T> {
404} 404}
405 405
406/// The result of the subscriber wait procedure 406/// The result of the subscriber wait procedure
407#[derive(Debug, Clone, PartialEq)] 407#[derive(Debug, Clone, PartialEq, Eq)]
408#[cfg_attr(feature = "defmt", derive(defmt::Format))] 408#[cfg_attr(feature = "defmt", derive(defmt::Format))]
409pub enum WaitResult<T> { 409pub enum WaitResult<T> {
410 /// The subscriber did not receive all messages and lagged by the given amount of messages. 410 /// The subscriber did not receive all messages and lagged by the given amount of messages.
diff --git a/embassy/src/channel/signal.rs b/embassy/src/channel/signal.rs
index cf78dad8b..3f3c482fb 100644
--- a/embassy/src/channel/signal.rs
+++ b/embassy/src/channel/signal.rs
@@ -4,11 +4,19 @@ use core::future::Future;
4use core::mem; 4use core::mem;
5use core::task::{Context, Poll, Waker}; 5use core::task::{Context, Poll, Waker};
6 6
7/// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks. 7/// Single-slot signaling primitive.
8/// For a simple use-case where the receiver is only ever interested in the latest value of
9/// something, Signals work well. For more advanced use cases, you might want to use [`Channel`](crate::channel::mpmc::Channel) instead..
10/// 8///
11/// Signals are generally declared as being a static const and then borrowed as required. 9/// This is similar to a [`Channel`](crate::channel::mpmc::Channel) with a buffer size of 1, except
10/// "sending" to it (calling [`Signal::signal`]) when full will overwrite the previous value instead
11/// of waiting for the receiver to pop the previous value.
12///
13/// It is useful for sending data between tasks when the receiver only cares about
14/// the latest data, and therefore it's fine to "lose" messages. This is often the case for "state"
15/// updates.
16///
17/// For more advanced use cases, you might want to use [`Channel`](crate::channel::mpmc::Channel) instead.
18///
19/// Signals are generally declared as `static`s and then borrowed as required.
12/// 20///
13/// ``` 21/// ```
14/// use embassy::channel::signal::Signal; 22/// use embassy::channel::signal::Signal;
@@ -34,6 +42,7 @@ unsafe impl<T: Send> Send for Signal<T> {}
34unsafe impl<T: Send> Sync for Signal<T> {} 42unsafe impl<T: Send> Sync for Signal<T> {}
35 43
36impl<T> Signal<T> { 44impl<T> Signal<T> {
45 /// Create a new `Signal`.
37 pub const fn new() -> Self { 46 pub const fn new() -> Self {
38 Self { 47 Self {
39 state: UnsafeCell::new(State::None), 48 state: UnsafeCell::new(State::None),
@@ -42,7 +51,7 @@ impl<T> Signal<T> {
42} 51}
43 52
44impl<T: Send> Signal<T> { 53impl<T: Send> Signal<T> {
45 /// Mark this Signal as completed. 54 /// Mark this Signal as signaled.
46 pub fn signal(&self, val: T) { 55 pub fn signal(&self, val: T) {
47 critical_section::with(|_| unsafe { 56 critical_section::with(|_| unsafe {
48 let state = &mut *self.state.get(); 57 let state = &mut *self.state.get();
@@ -52,6 +61,7 @@ impl<T: Send> Signal<T> {
52 }) 61 })
53 } 62 }
54 63
64 /// Remove the queued value in this `Signal`, if any.
55 pub fn reset(&self) { 65 pub fn reset(&self) {
56 critical_section::with(|_| unsafe { 66 critical_section::with(|_| unsafe {
57 let state = &mut *self.state.get(); 67 let state = &mut *self.state.get();
@@ -59,7 +69,7 @@ impl<T: Send> Signal<T> {
59 }) 69 })
60 } 70 }
61 71
62 pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { 72 fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> {
63 critical_section::with(|_| unsafe { 73 critical_section::with(|_| unsafe {
64 let state = &mut *self.state.get(); 74 let state = &mut *self.state.get();
65 match state { 75 match state {
diff --git a/embassy/src/executor/raw/mod.rs b/embassy/src/executor/raw/mod.rs
index b8455442e..7e8559168 100644
--- a/embassy/src/executor/raw/mod.rs
+++ b/embassy/src/executor/raw/mod.rs
@@ -445,6 +445,10 @@ impl Executor {
445/// Wake a task by raw pointer. 445/// Wake a task by raw pointer.
446/// 446///
447/// You can obtain task pointers from `Waker`s using [`task_from_waker`]. 447/// You can obtain task pointers from `Waker`s using [`task_from_waker`].
448///
449/// # Safety
450///
451/// `task` must be a valid task pointer obtained from [`task_from_waker`].
448pub unsafe fn wake_task(task: NonNull<TaskHeader>) { 452pub unsafe fn wake_task(task: NonNull<TaskHeader>) {
449 task.as_ref().enqueue(); 453 task.as_ref().enqueue();
450} 454}
diff --git a/embassy/src/executor/raw/waker.rs b/embassy/src/executor/raw/waker.rs
index ea9010ca0..605cda4ca 100644
--- a/embassy/src/executor/raw/waker.rs
+++ b/embassy/src/executor/raw/waker.rs
@@ -33,12 +33,18 @@ pub(crate) unsafe fn from_task(p: NonNull<TaskHeader>) -> Waker {
33/// # Panics 33/// # Panics
34/// 34///
35/// Panics if the waker is not created by the Embassy executor. 35/// Panics if the waker is not created by the Embassy executor.
36pub unsafe fn task_from_waker(waker: &Waker) -> NonNull<TaskHeader> { 36pub fn task_from_waker(waker: &Waker) -> NonNull<TaskHeader> {
37 let hack: &WakerHack = mem::transmute(waker); 37 // safety: OK because WakerHack has the same layout as Waker.
38 // This is not really guaranteed because the structs are `repr(Rust)`, it is
39 // indeed the case in the current implementation.
40 // TODO use waker_getters when stable. https://github.com/rust-lang/rust/issues/96992
41 let hack: &WakerHack = unsafe { mem::transmute(waker) };
38 if hack.vtable != &VTABLE { 42 if hack.vtable != &VTABLE {
39 panic!("Found waker not created by the embassy executor. Consider enabling the `executor-agnostic` feature on the `embassy` crate.") 43 panic!("Found waker not created by the embassy executor. Consider enabling the `executor-agnostic` feature on the `embassy` crate.")
40 } 44 }
41 NonNull::new_unchecked(hack.data as *mut TaskHeader) 45
46 // safety: we never create a waker with a null data pointer.
47 unsafe { NonNull::new_unchecked(hack.data as *mut TaskHeader) }
42} 48}
43 49
44struct WakerHack { 50struct WakerHack {
diff --git a/embassy/src/executor/spawner.rs b/embassy/src/executor/spawner.rs
index 884db6b55..c8d036eb8 100644
--- a/embassy/src/executor/spawner.rs
+++ b/embassy/src/executor/spawner.rs
@@ -93,7 +93,7 @@ impl Spawner {
93 pub async fn for_current_executor() -> Self { 93 pub async fn for_current_executor() -> Self {
94 poll_fn(|cx| unsafe { 94 poll_fn(|cx| unsafe {
95 let task = raw::task_from_waker(cx.waker()); 95 let task = raw::task_from_waker(cx.waker());
96 let executor = (&*task.as_ptr()).executor.get(); 96 let executor = (*task.as_ptr()).executor.get();
97 Poll::Ready(Self::new(&*executor)) 97 Poll::Ready(Self::new(&*executor))
98 }) 98 })
99 .await 99 .await
@@ -169,7 +169,7 @@ impl SendSpawner {
169 pub async fn for_current_executor() -> Self { 169 pub async fn for_current_executor() -> Self {
170 poll_fn(|cx| unsafe { 170 poll_fn(|cx| unsafe {
171 let task = raw::task_from_waker(cx.waker()); 171 let task = raw::task_from_waker(cx.waker());
172 let executor = (&*task.as_ptr()).executor.get(); 172 let executor = (*task.as_ptr()).executor.get();
173 Poll::Ready(Self::new(&*executor)) 173 Poll::Ready(Self::new(&*executor))
174 }) 174 })
175 .await 175 .await
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs
index c0a0deabf..b7be8b34c 100644
--- a/embassy/src/lib.rs
+++ b/embassy/src/lib.rs
@@ -3,6 +3,7 @@
3#![cfg_attr(all(feature = "nightly", target_arch = "xtensa"), feature(asm_experimental_arch))] 3#![cfg_attr(all(feature = "nightly", target_arch = "xtensa"), feature(asm_experimental_arch))]
4#![allow(clippy::new_without_default)] 4#![allow(clippy::new_without_default)]
5#![doc = include_str!("../../README.md")] 5#![doc = include_str!("../../README.md")]
6#![warn(missing_docs)]
6 7
7// This mod MUST go first, so that the others see its macros. 8// This mod MUST go first, so that the others see its macros.
8pub(crate) mod fmt; 9pub(crate) mod fmt;
diff --git a/embassy/src/util/forever.rs b/embassy/src/util/forever.rs
index e367d2643..ba3c66a91 100644
--- a/embassy/src/util/forever.rs
+++ b/embassy/src/util/forever.rs
@@ -31,6 +31,7 @@ unsafe impl<T> Send for Forever<T> {}
31unsafe impl<T> Sync for Forever<T> {} 31unsafe impl<T> Sync for Forever<T> {}
32 32
33impl<T> Forever<T> { 33impl<T> Forever<T> {
34 /// Create a new `Forever`.
34 #[inline(always)] 35 #[inline(always)]
35 pub const fn new() -> Self { 36 pub const fn new() -> Self {
36 Self { 37 Self {
@@ -39,11 +40,15 @@ impl<T> Forever<T> {
39 } 40 }
40 } 41 }
41 42
42 /// Gives this `Forever` a value. 43 /// Store a value in this `Forever`, returning a mutable reference to it.
43 /// 44 ///
44 /// Panics if this `Forever` already has a value. 45 /// Using this method, the compiler usually constructs `val` in the stack and then moves
46 /// it into the `Forever`. If `T` is big, this is likely to cause stack overflows.
47 /// Considering using [`Signal::put_with`] instead, which will construct it in-place inside the `Forever`.
45 /// 48 ///
46 /// Returns a mutable reference to the stored value. 49 /// # Panics
50 ///
51 /// Panics if this `Forever` already has a value stored in it.
47 #[inline(always)] 52 #[inline(always)]
48 #[allow(clippy::mut_from_ref)] 53 #[allow(clippy::mut_from_ref)]
49 pub fn put(&'static self, val: T) -> &'static mut T { 54 pub fn put(&'static self, val: T) -> &'static mut T {
@@ -52,7 +57,7 @@ impl<T> Forever<T> {
52 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) 57 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
53 .is_err() 58 .is_err()
54 { 59 {
55 panic!("Forever.put() called multiple times"); 60 panic!("Forever::put() called multiple times");
56 } 61 }
57 62
58 unsafe { 63 unsafe {
@@ -63,6 +68,14 @@ impl<T> Forever<T> {
63 } 68 }
64 } 69 }
65 70
71 /// Store the closure return value in this `Forever`, returning a mutable reference to it.
72 ///
73 /// The advantage over [`Forever::put`] is that this method allows the closure to construct
74 /// the `T` value in-place directly inside the `Forever`, saving stack space.
75 ///
76 /// # Panics
77 ///
78 /// Panics if this `Forever` already has a value stored in it.
66 #[inline(always)] 79 #[inline(always)]
67 #[allow(clippy::mut_from_ref)] 80 #[allow(clippy::mut_from_ref)]
68 pub fn put_with(&'static self, val: impl FnOnce() -> T) -> &'static mut T { 81 pub fn put_with(&'static self, val: impl FnOnce() -> T) -> &'static mut T {
@@ -82,9 +95,17 @@ impl<T> Forever<T> {
82 } 95 }
83 } 96 }
84 97
98 /// Unsafely get a mutable reference to the contents of this Forever.
99 ///
100 /// # Safety
101 ///
102 /// This is undefined behavior if:
103 ///
104 /// - The `Forever` has not been initialized yet (with `put' or `put_with`), or
105 /// - A reference to the contents (mutable or not) already exists.
85 #[inline(always)] 106 #[inline(always)]
86 #[allow(clippy::mut_from_ref)] 107 #[allow(clippy::mut_from_ref)]
87 pub unsafe fn steal(&'static self) -> &'static mut T { 108 pub unsafe fn steal(&self) -> &mut T {
88 let p = self.t.get(); 109 let p = self.t.get();
89 let p = (&mut *p).as_mut_ptr(); 110 let p = (&mut *p).as_mut_ptr();
90 &mut *p 111 &mut *p
diff --git a/embassy/src/util/select.rs b/embassy/src/util/select.rs
index ccc50f117..8cecb7fa0 100644
--- a/embassy/src/util/select.rs
+++ b/embassy/src/util/select.rs
@@ -2,9 +2,12 @@ use core::future::Future;
2use core::pin::Pin; 2use core::pin::Pin;
3use core::task::{Context, Poll}; 3use core::task::{Context, Poll};
4 4
5/// Result for [`select`].
5#[derive(Debug, Clone)] 6#[derive(Debug, Clone)]
6pub enum Either<A, B> { 7pub enum Either<A, B> {
8 /// First future finished first.
7 First(A), 9 First(A),
10 /// Second future finished first.
8 Second(B), 11 Second(B),
9} 12}
10 13
@@ -55,10 +58,14 @@ where
55 58
56// ==================================================================== 59// ====================================================================
57 60
61/// Result for [`select3`].
58#[derive(Debug, Clone)] 62#[derive(Debug, Clone)]
59pub enum Either3<A, B, C> { 63pub enum Either3<A, B, C> {
64 /// First future finished first.
60 First(A), 65 First(A),
66 /// Second future finished first.
61 Second(B), 67 Second(B),
68 /// Third future finished first.
62 Third(C), 69 Third(C),
63} 70}
64 71
@@ -109,11 +116,16 @@ where
109 116
110// ==================================================================== 117// ====================================================================
111 118
119/// Result for [`select4`].
112#[derive(Debug, Clone)] 120#[derive(Debug, Clone)]
113pub enum Either4<A, B, C, D> { 121pub enum Either4<A, B, C, D> {
122 /// First future finished first.
114 First(A), 123 First(A),
124 /// Second future finished first.
115 Second(B), 125 Second(B),
126 /// Third future finished first.
116 Third(C), 127 Third(C),
128 /// Fourth future finished first.
117 Fourth(D), 129 Fourth(D),
118} 130}
119 131
diff --git a/embassy/src/waitqueue/waker.rs b/embassy/src/waitqueue/waker.rs
index a90154cce..cdc96507f 100644
--- a/embassy/src/waitqueue/waker.rs
+++ b/embassy/src/waitqueue/waker.rs
@@ -16,13 +16,14 @@ pub struct WakerRegistration {
16} 16}
17 17
18impl WakerRegistration { 18impl WakerRegistration {
19 /// Create a new `WakerRegistration`.
19 pub const fn new() -> Self { 20 pub const fn new() -> Self {
20 Self { waker: None } 21 Self { waker: None }
21 } 22 }
22 23
23 /// Register a waker. Overwrites the previous waker, if any. 24 /// Register a waker. Overwrites the previous waker, if any.
24 pub fn register(&mut self, w: &Waker) { 25 pub fn register(&mut self, w: &Waker) {
25 let w = unsafe { task_from_waker(w) }; 26 let w = task_from_waker(w);
26 match self.waker { 27 match self.waker {
27 // Optimization: If both the old and new Wakers wake the same task, do nothing. 28 // Optimization: If both the old and new Wakers wake the same task, do nothing.
28 Some(w2) if w == w2 => {} 29 Some(w2) if w == w2 => {}
@@ -72,6 +73,7 @@ pub struct AtomicWaker {
72} 73}
73 74
74impl AtomicWaker { 75impl AtomicWaker {
76 /// Create a new `AtomicWaker`.
75 pub const fn new() -> Self { 77 pub const fn new() -> Self {
76 Self { 78 Self {
77 waker: AtomicPtr::new(ptr::null_mut()), 79 waker: AtomicPtr::new(ptr::null_mut()),
@@ -80,7 +82,7 @@ impl AtomicWaker {
80 82
81 /// Register a waker. Overwrites the previous waker, if any. 83 /// Register a waker. Overwrites the previous waker, if any.
82 pub fn register(&self, w: &Waker) { 84 pub fn register(&self, w: &Waker) {
83 let w = unsafe { task_from_waker(w) }; 85 let w = task_from_waker(w);
84 self.waker.store(w.as_ptr(), Ordering::Relaxed); 86 self.waker.store(w.as_ptr(), Ordering::Relaxed);
85 compiler_fence(Ordering::SeqCst); 87 compiler_fence(Ordering::SeqCst);
86 } 88 }
diff --git a/embassy/src/waitqueue/waker_agnostic.rs b/embassy/src/waitqueue/waker_agnostic.rs
index 62e3adb79..64e300eb8 100644
--- a/embassy/src/waitqueue/waker_agnostic.rs
+++ b/embassy/src/waitqueue/waker_agnostic.rs
@@ -12,6 +12,7 @@ pub struct WakerRegistration {
12} 12}
13 13
14impl WakerRegistration { 14impl WakerRegistration {
15 /// Create a new `WakerRegistration`.
15 pub const fn new() -> Self { 16 pub const fn new() -> Self {
16 Self { waker: None } 17 Self { waker: None }
17 } 18 }
@@ -60,6 +61,7 @@ pub struct AtomicWaker {
60} 61}
61 62
62impl AtomicWaker { 63impl AtomicWaker {
64 /// Create a new `AtomicWaker`.
63 pub const fn new() -> Self { 65 pub const fn new() -> Self {
64 Self { 66 Self {
65 waker: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), 67 waker: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),