diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-06-16 07:18:43 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-06-16 07:18:43 +0000 |
| commit | 23177ba7eb800d32a48f70fe568ae9bf6b2cde98 (patch) | |
| tree | f259b15d26428b8a448e5c14f055a975138470c0 | |
| parent | a8920bced5e72ca130e92c7680c2d839794d31f6 (diff) | |
| parent | 25ddb26be815ec3029ea9d28ba812bd541a0face (diff) | |
Merge #813
813: Document remaining public APIs in embassy crate r=lulf a=lulf
This also includes the README.md in the toplevel crate documentation, fixing a few formatting issues with it as well.
Please review the mutex in detail in case I've misunderstood/missed a few things there.
Co-authored-by: Ulf Lilleengen <[email protected]>
| -rw-r--r-- | README.md | 17 | ||||
| -rw-r--r-- | embassy/src/blocking_mutex/mod.rs | 34 | ||||
| -rw-r--r-- | embassy/src/blocking_mutex/raw.rs | 23 | ||||
| -rw-r--r-- | embassy/src/channel/mpmc.rs | 2 | ||||
| -rw-r--r-- | embassy/src/channel/signal.rs | 1 | ||||
| -rw-r--r-- | embassy/src/executor/raw/mod.rs | 8 | ||||
| -rw-r--r-- | embassy/src/lib.rs | 1 | ||||
| -rw-r--r-- | embassy/src/mutex.rs | 24 | ||||
| -rw-r--r-- | embassy/src/util/steal.rs | 10 | ||||
| -rw-r--r-- | embassy/src/waitqueue/waker.rs | 9 |
10 files changed, 105 insertions, 24 deletions
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | Embassy is the next-generation framework for embedded applications. Write safe, correct and energy-efficient embedded code faster, using the Rust programming language, its async facilities, and the Embassy libraries. | 3 | Embassy is the next-generation framework for embedded applications. Write safe, correct and energy-efficient embedded code faster, using the Rust programming language, its async facilities, and the Embassy libraries. |
| 4 | 4 | ||
| 5 | ## [Documentation](https://embassy.dev/embassy/dev/index.html) - [API reference](https://docs.embassy.dev/) - [Website](https://embassy.dev/) - [Chat](https://matrix.to/#/#embassy-rs:matrix.org) | 5 | ## <a href="https://embassy.dev/embassy/dev/index.html">Documentation</a> - <a href="https://docs.embassy.dev/">API reference</a> - <a href="https://embassy.dev/">Website</a> - <a href="https://matrix.to/#/#embassy-rs:matrix.org">Chat</a> |
| 6 | ## Rust + async ❤️ embedded | 6 | ## Rust + async ❤️ embedded |
| 7 | 7 | ||
| 8 | The Rust programming language is blazingly fast and memory-efficient, with no runtime, garbage collector or OS. It catches a wide variety of bugs at compile time, thanks to its full memory- and thread-safety, and expressive type system. | 8 | The Rust programming language is blazingly fast and memory-efficient, with no runtime, garbage collector or OS. It catches a wide variety of bugs at compile time, thanks to its full memory- and thread-safety, and expressive type system. |
| @@ -42,7 +42,7 @@ The <a href="https://github.com/embassy-rs/nrf-softdevice">nrf-softdevice</a> cr | |||
| 42 | 42 | ||
| 43 | ## Sneak peek | 43 | ## Sneak peek |
| 44 | 44 | ||
| 45 | ```rust | 45 | ```rust,ignore |
| 46 | use defmt::info; | 46 | use defmt::info; |
| 47 | use embassy::executor::Spawner; | 47 | use embassy::executor::Spawner; |
| 48 | use embassy::time::{Duration, Timer}; | 48 | use embassy::time::{Duration, Timer}; |
| @@ -93,20 +93,21 @@ Examples are found in the `examples/` folder seperated by the chip manufacturer | |||
| 93 | ### Running examples | 93 | ### Running examples |
| 94 | 94 | ||
| 95 | - Setup git submodules (needed for STM32 examples) | 95 | - Setup git submodules (needed for STM32 examples) |
| 96 | ``` | 96 | |
| 97 | ```bash | ||
| 97 | git submodule init | 98 | git submodule init |
| 98 | git submodule update | 99 | git submodule update |
| 99 | ``` | 100 | ``` |
| 100 | 101 | ||
| 101 | - Install `probe-run` with defmt support. | 102 | - Install `probe-run` with defmt support. |
| 102 | 103 | ||
| 103 | ``` | 104 | ```bash |
| 104 | cargo install probe-run | 105 | cargo install probe-run |
| 105 | ``` | 106 | ``` |
| 106 | 107 | ||
| 107 | - Change directory to the sample's base directory. For example: | 108 | - Change directory to the sample's base directory. For example: |
| 108 | 109 | ||
| 109 | ``` | 110 | ```bash |
| 110 | cd examples/nrf | 111 | cd examples/nrf |
| 111 | ``` | 112 | ``` |
| 112 | 113 | ||
| @@ -114,7 +115,7 @@ cd examples/nrf | |||
| 114 | 115 | ||
| 115 | For example: | 116 | For example: |
| 116 | 117 | ||
| 117 | ``` | 118 | ```bash |
| 118 | cargo run --bin blinky | 119 | cargo run --bin blinky |
| 119 | ``` | 120 | ``` |
| 120 | 121 | ||
| @@ -145,8 +146,8 @@ EMBedded ASYnc! :) | |||
| 145 | This work is licensed under either of | 146 | This work is licensed under either of |
| 146 | 147 | ||
| 147 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or | 148 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or |
| 148 | http://www.apache.org/licenses/LICENSE-2.0) | 149 | <http://www.apache.org/licenses/LICENSE-2.0>) |
| 149 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) | 150 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>) |
| 150 | 151 | ||
| 151 | at your option. | 152 | at your option. |
| 152 | 153 | ||
diff --git a/embassy/src/blocking_mutex/mod.rs b/embassy/src/blocking_mutex/mod.rs index eb3cd9392..602ec8a07 100644 --- a/embassy/src/blocking_mutex/mod.rs +++ b/embassy/src/blocking_mutex/mod.rs | |||
| @@ -1,14 +1,27 @@ | |||
| 1 | //! Blocking mutex (not async) | 1 | //! Blocking mutex. |
| 2 | 2 | //! | |
| 3 | //! This module provides a blocking mutex that can be used to synchronize data. | ||
| 3 | pub mod raw; | 4 | pub mod raw; |
| 4 | 5 | ||
| 5 | use core::cell::UnsafeCell; | 6 | use core::cell::UnsafeCell; |
| 6 | 7 | ||
| 7 | use self::raw::RawMutex; | 8 | use self::raw::RawMutex; |
| 8 | 9 | ||
| 9 | /// Any object implementing this trait guarantees exclusive access to the data contained | 10 | /// Blocking mutex (not async) |
| 10 | /// within the mutex for the duration of the lock. | 11 | /// |
| 11 | /// Adapted from <https://github.com/rust-embedded/mutex-trait>. | 12 | /// Provides a blocking mutual exclusion primitive backed by an implementation of [`raw::RawMutex`]. |
| 13 | /// | ||
| 14 | /// Which implementation you select depends on the context in which you're using the mutex, and you can choose which kind | ||
| 15 | /// of interior mutability fits your use case. | ||
| 16 | /// | ||
| 17 | /// Use [`CriticalSectionMutex`] when data can be shared between threads and interrupts. | ||
| 18 | /// | ||
| 19 | /// Use [`NoopMutex`] when data is only shared between tasks running on the same executor. | ||
| 20 | /// | ||
| 21 | /// Use [`ThreadModeMutex`] when data is shared between tasks running on the same executor but you want a global singleton. | ||
| 22 | /// | ||
| 23 | /// In all cases, the blocking mutex is intended to be short lived and not held across await points. | ||
| 24 | /// Use the async [`Mutex`](crate::mutex::Mutex) if you need a lock that is held across await points. | ||
| 12 | pub struct Mutex<R, T: ?Sized> { | 25 | pub struct Mutex<R, T: ?Sized> { |
| 13 | // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets | 26 | // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets |
| 14 | // to run BEFORE dropping `data`. | 27 | // to run BEFORE dropping `data`. |
| @@ -78,7 +91,18 @@ impl<R, T> Mutex<R, T> { | |||
| 78 | } | 91 | } |
| 79 | } | 92 | } |
| 80 | 93 | ||
| 94 | /// A mutex that allows borrowing data across executors and interrupts. | ||
| 95 | /// | ||
| 96 | /// # Safety | ||
| 97 | /// | ||
| 98 | /// This mutex is safe to share between different executors and interrupts. | ||
| 81 | pub type CriticalSectionMutex<T> = Mutex<raw::CriticalSectionRawMutex, T>; | 99 | pub type CriticalSectionMutex<T> = Mutex<raw::CriticalSectionRawMutex, T>; |
| 100 | |||
| 101 | /// A mutex that allows borrowing data in the context of a single executor. | ||
| 102 | /// | ||
| 103 | /// # Safety | ||
| 104 | /// | ||
| 105 | /// **This Mutex is only safe within a single executor.** | ||
| 82 | pub type NoopMutex<T> = Mutex<raw::NoopRawMutex, T>; | 106 | pub type NoopMutex<T> = Mutex<raw::NoopRawMutex, T>; |
| 83 | 107 | ||
| 84 | impl<T> Mutex<raw::CriticalSectionRawMutex, T> { | 108 | impl<T> Mutex<raw::CriticalSectionRawMutex, T> { |
diff --git a/embassy/src/blocking_mutex/raw.rs b/embassy/src/blocking_mutex/raw.rs index f9d249b08..bdb443e4d 100644 --- a/embassy/src/blocking_mutex/raw.rs +++ b/embassy/src/blocking_mutex/raw.rs | |||
| @@ -1,11 +1,22 @@ | |||
| 1 | //! Mutex primitives. | ||
| 2 | //! | ||
| 3 | //! This module provides a trait for mutexes that can be used in different contexts. | ||
| 1 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 2 | 5 | ||
| 6 | /// Any object implementing this trait guarantees exclusive access to the data contained | ||
| 7 | /// within the mutex for the duration of the lock. | ||
| 8 | /// Adapted from <https://github.com/rust-embedded/mutex-trait>. | ||
| 3 | pub trait RawMutex { | 9 | pub trait RawMutex { |
| 4 | const INIT: Self; | 10 | const INIT: Self; |
| 5 | 11 | ||
| 6 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R; | 12 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R; |
| 7 | } | 13 | } |
| 8 | 14 | ||
| 15 | /// A mutex that allows borrowing data across executors and interrupts. | ||
| 16 | /// | ||
| 17 | /// # Safety | ||
| 18 | /// | ||
| 19 | /// This mutex is safe to share between different executors and interrupts. | ||
| 9 | pub struct CriticalSectionRawMutex { | 20 | pub struct CriticalSectionRawMutex { |
| 10 | _phantom: PhantomData<()>, | 21 | _phantom: PhantomData<()>, |
| 11 | } | 22 | } |
| @@ -28,6 +39,11 @@ impl RawMutex for CriticalSectionRawMutex { | |||
| 28 | 39 | ||
| 29 | // ================ | 40 | // ================ |
| 30 | 41 | ||
| 42 | /// A mutex that allows borrowing data in the context of a single executor. | ||
| 43 | /// | ||
| 44 | /// # Safety | ||
| 45 | /// | ||
| 46 | /// **This Mutex is only safe within a single executor.** | ||
| 31 | pub struct NoopRawMutex { | 47 | pub struct NoopRawMutex { |
| 32 | _phantom: PhantomData<*mut ()>, | 48 | _phantom: PhantomData<*mut ()>, |
| 33 | } | 49 | } |
| @@ -53,6 +69,13 @@ impl RawMutex for NoopRawMutex { | |||
| 53 | mod thread_mode { | 69 | mod thread_mode { |
| 54 | use super::*; | 70 | use super::*; |
| 55 | 71 | ||
| 72 | /// A "mutex" that only allows borrowing from thread mode. | ||
| 73 | /// | ||
| 74 | /// # Safety | ||
| 75 | /// | ||
| 76 | /// **This Mutex is only safe on single-core systems.** | ||
| 77 | /// | ||
| 78 | /// On multi-core systems, a `ThreadModeRawMutex` **is not sufficient** to ensure exclusive access. | ||
| 56 | pub struct ThreadModeRawMutex { | 79 | pub struct ThreadModeRawMutex { |
| 57 | _phantom: PhantomData<()>, | 80 | _phantom: PhantomData<()>, |
| 58 | } | 81 | } |
diff --git a/embassy/src/channel/mpmc.rs b/embassy/src/channel/mpmc.rs index 48056cd8f..1d03eef19 100644 --- a/embassy/src/channel/mpmc.rs +++ b/embassy/src/channel/mpmc.rs | |||
| @@ -433,7 +433,7 @@ where | |||
| 433 | 433 | ||
| 434 | /// Attempt to immediately send a message. | 434 | /// Attempt to immediately send a message. |
| 435 | /// | 435 | /// |
| 436 | /// This method differs from [`send`] by returning immediately if the channel's | 436 | /// This method differs from [`send`](Channel::send) by returning immediately if the channel's |
| 437 | /// buffer is full, instead of waiting. | 437 | /// buffer is full, instead of waiting. |
| 438 | /// | 438 | /// |
| 439 | /// # Errors | 439 | /// # Errors |
diff --git a/embassy/src/channel/signal.rs b/embassy/src/channel/signal.rs index 5a2c9d47a..cf78dad8b 100644 --- a/embassy/src/channel/signal.rs +++ b/embassy/src/channel/signal.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! A synchronization primitive for passing the latest value to a task. | ||
| 1 | use core::cell::UnsafeCell; | 2 | use core::cell::UnsafeCell; |
| 2 | use core::future::Future; | 3 | use core::future::Future; |
| 3 | use core::mem; | 4 | use core::mem; |
diff --git a/embassy/src/executor/raw/mod.rs b/embassy/src/executor/raw/mod.rs index 09429c19a..b8455442e 100644 --- a/embassy/src/executor/raw/mod.rs +++ b/embassy/src/executor/raw/mod.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | //! ## WARNING: here be dragons! | 5 | //! ## WARNING: here be dragons! |
| 6 | //! | 6 | //! |
| 7 | //! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe | 7 | //! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe |
| 8 | //! executor wrappers in [`crate::executor`] and the [`crate::task`] macro, which are fully safe. | 8 | //! executor wrappers in [`executor`](crate::executor) and the [`embassy::task`](embassy_macros::task) macro, which are fully safe. |
| 9 | 9 | ||
| 10 | mod run_queue; | 10 | mod run_queue; |
| 11 | #[cfg(feature = "time")] | 11 | #[cfg(feature = "time")] |
| @@ -115,7 +115,7 @@ impl TaskHeader { | |||
| 115 | /// A `TaskStorage` must live forever, it may not be deallocated even after the task has finished | 115 | /// A `TaskStorage` must live forever, it may not be deallocated even after the task has finished |
| 116 | /// running. Hence the relevant methods require `&'static self`. It may be reused, however. | 116 | /// running. Hence the relevant methods require `&'static self`. It may be reused, however. |
| 117 | /// | 117 | /// |
| 118 | /// Internally, the [embassy::task](crate::task) macro allocates an array of `TaskStorage`s | 118 | /// Internally, the [embassy::task](embassy_macros::task) macro allocates an array of `TaskStorage`s |
| 119 | /// in a `static`. The most common reason to use the raw `Task` is to have control of where | 119 | /// in a `static`. The most common reason to use the raw `Task` is to have control of where |
| 120 | /// the memory for the task is allocated: on the stack, or on the heap with e.g. `Box::leak`, etc. | 120 | /// the memory for the task is allocated: on the stack, or on the heap with e.g. `Box::leak`, etc. |
| 121 | 121 | ||
| @@ -158,7 +158,7 @@ impl<F: Future + 'static> TaskStorage<F> { | |||
| 158 | /// | 158 | /// |
| 159 | /// This function will fail if the task is already spawned and has not finished running. | 159 | /// This function will fail if the task is already spawned and has not finished running. |
| 160 | /// In this case, the error is delayed: a "poisoned" SpawnToken is returned, which will | 160 | /// In this case, the error is delayed: a "poisoned" SpawnToken is returned, which will |
| 161 | /// cause [`Spawner::spawn()`] to return the error. | 161 | /// cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error. |
| 162 | /// | 162 | /// |
| 163 | /// Once the task has finished running, you may spawn it again. It is allowed to spawn it | 163 | /// Once the task has finished running, you may spawn it again. It is allowed to spawn it |
| 164 | /// on a different executor. | 164 | /// on a different executor. |
| @@ -230,7 +230,7 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> { | |||
| 230 | /// | 230 | /// |
| 231 | /// This will loop over the pool and spawn the task in the first storage that | 231 | /// This will loop over the pool and spawn the task in the first storage that |
| 232 | /// is currently free. If none is free, a "poisoned" SpawnToken is returned, | 232 | /// is currently free. If none is free, a "poisoned" SpawnToken is returned, |
| 233 | /// which will cause [`Spawner::spawn()`] to return the error. | 233 | /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error. |
| 234 | pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> { | 234 | pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> { |
| 235 | for task in &self.pool { | 235 | for task in &self.pool { |
| 236 | if task.spawn_mark_used() { | 236 | if task.spawn_mark_used() { |
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index 1b6ff2d4b..c3b2726aa 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] | 1 | #![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] |
| 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] |
| 3 | #![allow(clippy::new_without_default)] | 3 | #![allow(clippy::new_without_default)] |
| 4 | #![doc = include_str!("../../README.md")] | ||
| 4 | 5 | ||
| 5 | // This mod MUST go first, so that the others see its macros. | 6 | // This mod MUST go first, so that the others see its macros. |
| 6 | pub(crate) mod fmt; | 7 | pub(crate) mod fmt; |
diff --git a/embassy/src/mutex.rs b/embassy/src/mutex.rs index 7b6bcb147..9cfaaa845 100644 --- a/embassy/src/mutex.rs +++ b/embassy/src/mutex.rs | |||
| @@ -1,9 +1,6 @@ | |||
| 1 | /// Async mutex. | 1 | //! Async mutex. |
| 2 | /// | 2 | //! |
| 3 | /// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex). | 3 | //! This module provides a mutex that can be used to synchronize data between asynchronous tasks. |
| 4 | /// The raw mutex is used to guard access to the internal "is locked" flag. It | ||
| 5 | /// is held for very short periods only, while locking and unlocking. It is *not* held | ||
| 6 | /// for the entire time the async Mutex is locked. | ||
| 7 | use core::cell::{RefCell, UnsafeCell}; | 4 | use core::cell::{RefCell, UnsafeCell}; |
| 8 | use core::ops::{Deref, DerefMut}; | 5 | use core::ops::{Deref, DerefMut}; |
| 9 | use core::task::Poll; | 6 | use core::task::Poll; |
| @@ -24,6 +21,21 @@ struct State { | |||
| 24 | waker: WakerRegistration, | 21 | waker: WakerRegistration, |
| 25 | } | 22 | } |
| 26 | 23 | ||
| 24 | /// Async mutex. | ||
| 25 | /// | ||
| 26 | /// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex). | ||
| 27 | /// The raw mutex is used to guard access to the internal "is locked" flag. It | ||
| 28 | /// is held for very short periods only, while locking and unlocking. It is *not* held | ||
| 29 | /// for the entire time the async Mutex is locked. | ||
| 30 | /// | ||
| 31 | /// Which implementation you select depends on the context in which you're using the mutex. | ||
| 32 | /// | ||
| 33 | /// Use [`CriticalSectionRawMutex`](crate::blocking_mutex::raw::CriticalSectionRawMutex) when data can be shared between threads and interrupts. | ||
| 34 | /// | ||
| 35 | /// Use [`NoopRawMutex`](crate::blocking_mutex::raw::NoopRawMutex) when data is only shared between tasks running on the same executor. | ||
| 36 | /// | ||
| 37 | /// Use [`ThreadModeRawMutex`](crate::blocking_mutex::raw::ThreadModeRawMutex) when data is shared between tasks running on the same executor but you want a singleton. | ||
| 38 | /// | ||
| 27 | pub struct Mutex<M, T> | 39 | pub struct Mutex<M, T> |
| 28 | where | 40 | where |
| 29 | M: RawMutex, | 41 | M: RawMutex, |
diff --git a/embassy/src/util/steal.rs b/embassy/src/util/steal.rs index a0d5f1359..07eb5fffd 100644 --- a/embassy/src/util/steal.rs +++ b/embassy/src/util/steal.rs | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | /// A type that can retrieved unsafely from anywhere. | ||
| 1 | pub trait Steal { | 2 | pub trait Steal { |
| 3 | /// Retrieve and instance of this type. | ||
| 4 | /// | ||
| 5 | /// # Safety | ||
| 6 | /// | ||
| 7 | /// It is the responsibility of the application to ensure that the | ||
| 8 | /// usage of the returned instance is not in conflict with other uses | ||
| 9 | /// of this instance. | ||
| 10 | /// | ||
| 11 | /// The implementation may panic if the instance is already in use. | ||
| 2 | unsafe fn steal() -> Self; | 12 | unsafe fn steal() -> Self; |
| 3 | } | 13 | } |
diff --git a/embassy/src/waitqueue/waker.rs b/embassy/src/waitqueue/waker.rs index 1ac6054f9..da907300a 100644 --- a/embassy/src/waitqueue/waker.rs +++ b/embassy/src/waitqueue/waker.rs | |||
| @@ -6,6 +6,10 @@ use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering}; | |||
| 6 | use crate::executor::raw::{task_from_waker, wake_task, TaskHeader}; | 6 | use crate::executor::raw::{task_from_waker, wake_task, TaskHeader}; |
| 7 | 7 | ||
| 8 | /// Utility struct to register and wake a waker. | 8 | /// Utility struct to register and wake a waker. |
| 9 | /// | ||
| 10 | /// # Safety | ||
| 11 | /// | ||
| 12 | /// This type is optimized for (and only works with) embassy tasks. | ||
| 9 | #[derive(Debug)] | 13 | #[derive(Debug)] |
| 10 | pub struct WakerRegistration { | 14 | pub struct WakerRegistration { |
| 11 | waker: Option<NonNull<TaskHeader>>, | 15 | waker: Option<NonNull<TaskHeader>>, |
| @@ -53,6 +57,11 @@ impl WakerRegistration { | |||
| 53 | unsafe impl Send for WakerRegistration {} | 57 | unsafe impl Send for WakerRegistration {} |
| 54 | unsafe impl Sync for WakerRegistration {} | 58 | unsafe impl Sync for WakerRegistration {} |
| 55 | 59 | ||
| 60 | /// Utility struct to atomically register and wake a waker. | ||
| 61 | /// | ||
| 62 | /// # Safety | ||
| 63 | /// | ||
| 64 | /// This type is optimized for (and only works with) embassy tasks. | ||
| 56 | pub struct AtomicWaker { | 65 | pub struct AtomicWaker { |
| 57 | waker: AtomicPtr<TaskHeader>, | 66 | waker: AtomicPtr<TaskHeader>, |
| 58 | } | 67 | } |
