diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-08-22 21:46:09 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-08-22 22:18:13 +0200 |
| commit | 21072bee48ff6ec19b79e0d9527ad8cc34a4e9e0 (patch) | |
| tree | b5b8c0f4b3571989b5fd15152be5639f4334c282 /embassy-futures | |
| parent | 61356181b223e95f289ca3af3a038a699cde2112 (diff) | |
split `embassy-util` into `embassy-futures`, `embassy-sync`.
Diffstat (limited to 'embassy-futures')
| -rw-r--r-- | embassy-futures/Cargo.toml | 14 | ||||
| -rw-r--r-- | embassy-futures/src/fmt.rs | 228 | ||||
| -rw-r--r-- | embassy-futures/src/lib.rs | 12 | ||||
| -rw-r--r-- | embassy-futures/src/select.rs | 230 | ||||
| -rw-r--r-- | embassy-futures/src/yield_now.rs | 25 |
5 files changed, 509 insertions, 0 deletions
diff --git a/embassy-futures/Cargo.toml b/embassy-futures/Cargo.toml new file mode 100644 index 000000000..e564f5a96 --- /dev/null +++ b/embassy-futures/Cargo.toml | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-futures" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | |||
| 6 | [package.metadata.embassy_docs] | ||
| 7 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-futures-v$VERSION/embassy-futures/src/" | ||
| 8 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-futures/src/" | ||
| 9 | features = ["nightly"] | ||
| 10 | target = "thumbv7em-none-eabi" | ||
| 11 | |||
| 12 | [dependencies] | ||
| 13 | defmt = { version = "0.3", optional = true } | ||
| 14 | log = { version = "0.4.14", optional = true } | ||
diff --git a/embassy-futures/src/fmt.rs b/embassy-futures/src/fmt.rs new file mode 100644 index 000000000..f8bb0a035 --- /dev/null +++ b/embassy-futures/src/fmt.rs | |||
| @@ -0,0 +1,228 @@ | |||
| 1 | #![macro_use] | ||
| 2 | #![allow(unused_macros)] | ||
| 3 | |||
| 4 | #[cfg(all(feature = "defmt", feature = "log"))] | ||
| 5 | compile_error!("You may not enable both `defmt` and `log` features."); | ||
| 6 | |||
| 7 | macro_rules! assert { | ||
| 8 | ($($x:tt)*) => { | ||
| 9 | { | ||
| 10 | #[cfg(not(feature = "defmt"))] | ||
| 11 | ::core::assert!($($x)*); | ||
| 12 | #[cfg(feature = "defmt")] | ||
| 13 | ::defmt::assert!($($x)*); | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | macro_rules! assert_eq { | ||
| 19 | ($($x:tt)*) => { | ||
| 20 | { | ||
| 21 | #[cfg(not(feature = "defmt"))] | ||
| 22 | ::core::assert_eq!($($x)*); | ||
| 23 | #[cfg(feature = "defmt")] | ||
| 24 | ::defmt::assert_eq!($($x)*); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | macro_rules! assert_ne { | ||
| 30 | ($($x:tt)*) => { | ||
| 31 | { | ||
| 32 | #[cfg(not(feature = "defmt"))] | ||
| 33 | ::core::assert_ne!($($x)*); | ||
| 34 | #[cfg(feature = "defmt")] | ||
| 35 | ::defmt::assert_ne!($($x)*); | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | } | ||
| 39 | |||
| 40 | macro_rules! debug_assert { | ||
| 41 | ($($x:tt)*) => { | ||
| 42 | { | ||
| 43 | #[cfg(not(feature = "defmt"))] | ||
| 44 | ::core::debug_assert!($($x)*); | ||
| 45 | #[cfg(feature = "defmt")] | ||
| 46 | ::defmt::debug_assert!($($x)*); | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | } | ||
| 50 | |||
| 51 | macro_rules! debug_assert_eq { | ||
| 52 | ($($x:tt)*) => { | ||
| 53 | { | ||
| 54 | #[cfg(not(feature = "defmt"))] | ||
| 55 | ::core::debug_assert_eq!($($x)*); | ||
| 56 | #[cfg(feature = "defmt")] | ||
| 57 | ::defmt::debug_assert_eq!($($x)*); | ||
| 58 | } | ||
| 59 | }; | ||
| 60 | } | ||
| 61 | |||
| 62 | macro_rules! debug_assert_ne { | ||
| 63 | ($($x:tt)*) => { | ||
| 64 | { | ||
| 65 | #[cfg(not(feature = "defmt"))] | ||
| 66 | ::core::debug_assert_ne!($($x)*); | ||
| 67 | #[cfg(feature = "defmt")] | ||
| 68 | ::defmt::debug_assert_ne!($($x)*); | ||
| 69 | } | ||
| 70 | }; | ||
| 71 | } | ||
| 72 | |||
| 73 | macro_rules! todo { | ||
| 74 | ($($x:tt)*) => { | ||
| 75 | { | ||
| 76 | #[cfg(not(feature = "defmt"))] | ||
| 77 | ::core::todo!($($x)*); | ||
| 78 | #[cfg(feature = "defmt")] | ||
| 79 | ::defmt::todo!($($x)*); | ||
| 80 | } | ||
| 81 | }; | ||
| 82 | } | ||
| 83 | |||
| 84 | macro_rules! unreachable { | ||
| 85 | ($($x:tt)*) => { | ||
| 86 | { | ||
| 87 | #[cfg(not(feature = "defmt"))] | ||
| 88 | ::core::unreachable!($($x)*); | ||
| 89 | #[cfg(feature = "defmt")] | ||
| 90 | ::defmt::unreachable!($($x)*); | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | } | ||
| 94 | |||
| 95 | macro_rules! panic { | ||
| 96 | ($($x:tt)*) => { | ||
| 97 | { | ||
| 98 | #[cfg(not(feature = "defmt"))] | ||
| 99 | ::core::panic!($($x)*); | ||
| 100 | #[cfg(feature = "defmt")] | ||
| 101 | ::defmt::panic!($($x)*); | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | macro_rules! trace { | ||
| 107 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 108 | { | ||
| 109 | #[cfg(feature = "log")] | ||
| 110 | ::log::trace!($s $(, $x)*); | ||
| 111 | #[cfg(feature = "defmt")] | ||
| 112 | ::defmt::trace!($s $(, $x)*); | ||
| 113 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 114 | let _ = ($( & $x ),*); | ||
| 115 | } | ||
| 116 | }; | ||
| 117 | } | ||
| 118 | |||
| 119 | macro_rules! debug { | ||
| 120 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 121 | { | ||
| 122 | #[cfg(feature = "log")] | ||
| 123 | ::log::debug!($s $(, $x)*); | ||
| 124 | #[cfg(feature = "defmt")] | ||
| 125 | ::defmt::debug!($s $(, $x)*); | ||
| 126 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 127 | let _ = ($( & $x ),*); | ||
| 128 | } | ||
| 129 | }; | ||
| 130 | } | ||
| 131 | |||
| 132 | macro_rules! info { | ||
| 133 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 134 | { | ||
| 135 | #[cfg(feature = "log")] | ||
| 136 | ::log::info!($s $(, $x)*); | ||
| 137 | #[cfg(feature = "defmt")] | ||
| 138 | ::defmt::info!($s $(, $x)*); | ||
| 139 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 140 | let _ = ($( & $x ),*); | ||
| 141 | } | ||
| 142 | }; | ||
| 143 | } | ||
| 144 | |||
| 145 | macro_rules! warn { | ||
| 146 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 147 | { | ||
| 148 | #[cfg(feature = "log")] | ||
| 149 | ::log::warn!($s $(, $x)*); | ||
| 150 | #[cfg(feature = "defmt")] | ||
| 151 | ::defmt::warn!($s $(, $x)*); | ||
| 152 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 153 | let _ = ($( & $x ),*); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | } | ||
| 157 | |||
| 158 | macro_rules! error { | ||
| 159 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 160 | { | ||
| 161 | #[cfg(feature = "log")] | ||
| 162 | ::log::error!($s $(, $x)*); | ||
| 163 | #[cfg(feature = "defmt")] | ||
| 164 | ::defmt::error!($s $(, $x)*); | ||
| 165 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 166 | let _ = ($( & $x ),*); | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | |||
| 171 | #[cfg(feature = "defmt")] | ||
| 172 | macro_rules! unwrap { | ||
| 173 | ($($x:tt)*) => { | ||
| 174 | ::defmt::unwrap!($($x)*) | ||
| 175 | }; | ||
| 176 | } | ||
| 177 | |||
| 178 | #[cfg(not(feature = "defmt"))] | ||
| 179 | macro_rules! unwrap { | ||
| 180 | ($arg:expr) => { | ||
| 181 | match $crate::fmt::Try::into_result($arg) { | ||
| 182 | ::core::result::Result::Ok(t) => t, | ||
| 183 | ::core::result::Result::Err(e) => { | ||
| 184 | ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | }; | ||
| 188 | ($arg:expr, $($msg:expr),+ $(,)? ) => { | ||
| 189 | match $crate::fmt::Try::into_result($arg) { | ||
| 190 | ::core::result::Result::Ok(t) => t, | ||
| 191 | ::core::result::Result::Err(e) => { | ||
| 192 | ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | #[cfg(feature = "defmt-timestamp-uptime")] | ||
| 199 | defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() } | ||
| 200 | |||
| 201 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 202 | pub struct NoneError; | ||
| 203 | |||
| 204 | pub trait Try { | ||
| 205 | type Ok; | ||
| 206 | type Error; | ||
| 207 | fn into_result(self) -> Result<Self::Ok, Self::Error>; | ||
| 208 | } | ||
| 209 | |||
| 210 | impl<T> Try for Option<T> { | ||
| 211 | type Ok = T; | ||
| 212 | type Error = NoneError; | ||
| 213 | |||
| 214 | #[inline] | ||
| 215 | fn into_result(self) -> Result<T, NoneError> { | ||
| 216 | self.ok_or(NoneError) | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | impl<T, E> Try for Result<T, E> { | ||
| 221 | type Ok = T; | ||
| 222 | type Error = E; | ||
| 223 | |||
| 224 | #[inline] | ||
| 225 | fn into_result(self) -> Self { | ||
| 226 | self | ||
| 227 | } | ||
| 228 | } | ||
diff --git a/embassy-futures/src/lib.rs b/embassy-futures/src/lib.rs new file mode 100644 index 000000000..48c9c8574 --- /dev/null +++ b/embassy-futures/src/lib.rs | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![doc = include_str!("../../README.md")] | ||
| 3 | #![warn(missing_docs)] | ||
| 4 | |||
| 5 | // This mod MUST go first, so that the others see its macros. | ||
| 6 | pub(crate) mod fmt; | ||
| 7 | |||
| 8 | mod select; | ||
| 9 | mod yield_now; | ||
| 10 | |||
| 11 | pub use select::*; | ||
| 12 | pub use yield_now::*; | ||
diff --git a/embassy-futures/src/select.rs b/embassy-futures/src/select.rs new file mode 100644 index 000000000..8cecb7fa0 --- /dev/null +++ b/embassy-futures/src/select.rs | |||
| @@ -0,0 +1,230 @@ | |||
| 1 | use core::future::Future; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use core::task::{Context, Poll}; | ||
| 4 | |||
| 5 | /// Result for [`select`]. | ||
| 6 | #[derive(Debug, Clone)] | ||
| 7 | pub enum Either<A, B> { | ||
| 8 | /// First future finished first. | ||
| 9 | First(A), | ||
| 10 | /// Second future finished first. | ||
| 11 | Second(B), | ||
| 12 | } | ||
| 13 | |||
| 14 | /// Wait for one of two futures to complete. | ||
| 15 | /// | ||
| 16 | /// This function returns a new future which polls all the futures. | ||
| 17 | /// When one of them completes, it will complete with its result value. | ||
| 18 | /// | ||
| 19 | /// The other future is dropped. | ||
| 20 | pub fn select<A, B>(a: A, b: B) -> Select<A, B> | ||
| 21 | where | ||
| 22 | A: Future, | ||
| 23 | B: Future, | ||
| 24 | { | ||
| 25 | Select { a, b } | ||
| 26 | } | ||
| 27 | |||
| 28 | /// Future for the [`select`] function. | ||
| 29 | #[derive(Debug)] | ||
| 30 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 31 | pub struct Select<A, B> { | ||
| 32 | a: A, | ||
| 33 | b: B, | ||
| 34 | } | ||
| 35 | |||
| 36 | impl<A: Unpin, B: Unpin> Unpin for Select<A, B> {} | ||
| 37 | |||
| 38 | impl<A, B> Future for Select<A, B> | ||
| 39 | where | ||
| 40 | A: Future, | ||
| 41 | B: Future, | ||
| 42 | { | ||
| 43 | type Output = Either<A::Output, B::Output>; | ||
| 44 | |||
| 45 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 46 | let this = unsafe { self.get_unchecked_mut() }; | ||
| 47 | let a = unsafe { Pin::new_unchecked(&mut this.a) }; | ||
| 48 | let b = unsafe { Pin::new_unchecked(&mut this.b) }; | ||
| 49 | if let Poll::Ready(x) = a.poll(cx) { | ||
| 50 | return Poll::Ready(Either::First(x)); | ||
| 51 | } | ||
| 52 | if let Poll::Ready(x) = b.poll(cx) { | ||
| 53 | return Poll::Ready(Either::Second(x)); | ||
| 54 | } | ||
| 55 | Poll::Pending | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | // ==================================================================== | ||
| 60 | |||
| 61 | /// Result for [`select3`]. | ||
| 62 | #[derive(Debug, Clone)] | ||
| 63 | pub enum Either3<A, B, C> { | ||
| 64 | /// First future finished first. | ||
| 65 | First(A), | ||
| 66 | /// Second future finished first. | ||
| 67 | Second(B), | ||
| 68 | /// Third future finished first. | ||
| 69 | Third(C), | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Same as [`select`], but with more futures. | ||
| 73 | pub fn select3<A, B, C>(a: A, b: B, c: C) -> Select3<A, B, C> | ||
| 74 | where | ||
| 75 | A: Future, | ||
| 76 | B: Future, | ||
| 77 | C: Future, | ||
| 78 | { | ||
| 79 | Select3 { a, b, c } | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Future for the [`select3`] function. | ||
| 83 | #[derive(Debug)] | ||
| 84 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 85 | pub struct Select3<A, B, C> { | ||
| 86 | a: A, | ||
| 87 | b: B, | ||
| 88 | c: C, | ||
| 89 | } | ||
| 90 | |||
| 91 | impl<A, B, C> Future for Select3<A, B, C> | ||
| 92 | where | ||
| 93 | A: Future, | ||
| 94 | B: Future, | ||
| 95 | C: Future, | ||
| 96 | { | ||
| 97 | type Output = Either3<A::Output, B::Output, C::Output>; | ||
| 98 | |||
| 99 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 100 | let this = unsafe { self.get_unchecked_mut() }; | ||
| 101 | let a = unsafe { Pin::new_unchecked(&mut this.a) }; | ||
| 102 | let b = unsafe { Pin::new_unchecked(&mut this.b) }; | ||
| 103 | let c = unsafe { Pin::new_unchecked(&mut this.c) }; | ||
| 104 | if let Poll::Ready(x) = a.poll(cx) { | ||
| 105 | return Poll::Ready(Either3::First(x)); | ||
| 106 | } | ||
| 107 | if let Poll::Ready(x) = b.poll(cx) { | ||
| 108 | return Poll::Ready(Either3::Second(x)); | ||
| 109 | } | ||
| 110 | if let Poll::Ready(x) = c.poll(cx) { | ||
| 111 | return Poll::Ready(Either3::Third(x)); | ||
| 112 | } | ||
| 113 | Poll::Pending | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | // ==================================================================== | ||
| 118 | |||
| 119 | /// Result for [`select4`]. | ||
| 120 | #[derive(Debug, Clone)] | ||
| 121 | pub enum Either4<A, B, C, D> { | ||
| 122 | /// First future finished first. | ||
| 123 | First(A), | ||
| 124 | /// Second future finished first. | ||
| 125 | Second(B), | ||
| 126 | /// Third future finished first. | ||
| 127 | Third(C), | ||
| 128 | /// Fourth future finished first. | ||
| 129 | Fourth(D), | ||
| 130 | } | ||
| 131 | |||
| 132 | /// Same as [`select`], but with more futures. | ||
| 133 | pub fn select4<A, B, C, D>(a: A, b: B, c: C, d: D) -> Select4<A, B, C, D> | ||
| 134 | where | ||
| 135 | A: Future, | ||
| 136 | B: Future, | ||
| 137 | C: Future, | ||
| 138 | D: Future, | ||
| 139 | { | ||
| 140 | Select4 { a, b, c, d } | ||
| 141 | } | ||
| 142 | |||
| 143 | /// Future for the [`select4`] function. | ||
| 144 | #[derive(Debug)] | ||
| 145 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 146 | pub struct Select4<A, B, C, D> { | ||
| 147 | a: A, | ||
| 148 | b: B, | ||
| 149 | c: C, | ||
| 150 | d: D, | ||
| 151 | } | ||
| 152 | |||
| 153 | impl<A, B, C, D> Future for Select4<A, B, C, D> | ||
| 154 | where | ||
| 155 | A: Future, | ||
| 156 | B: Future, | ||
| 157 | C: Future, | ||
| 158 | D: Future, | ||
| 159 | { | ||
| 160 | type Output = Either4<A::Output, B::Output, C::Output, D::Output>; | ||
| 161 | |||
| 162 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 163 | let this = unsafe { self.get_unchecked_mut() }; | ||
| 164 | let a = unsafe { Pin::new_unchecked(&mut this.a) }; | ||
| 165 | let b = unsafe { Pin::new_unchecked(&mut this.b) }; | ||
| 166 | let c = unsafe { Pin::new_unchecked(&mut this.c) }; | ||
| 167 | let d = unsafe { Pin::new_unchecked(&mut this.d) }; | ||
| 168 | if let Poll::Ready(x) = a.poll(cx) { | ||
| 169 | return Poll::Ready(Either4::First(x)); | ||
| 170 | } | ||
| 171 | if let Poll::Ready(x) = b.poll(cx) { | ||
| 172 | return Poll::Ready(Either4::Second(x)); | ||
| 173 | } | ||
| 174 | if let Poll::Ready(x) = c.poll(cx) { | ||
| 175 | return Poll::Ready(Either4::Third(x)); | ||
| 176 | } | ||
| 177 | if let Poll::Ready(x) = d.poll(cx) { | ||
| 178 | return Poll::Ready(Either4::Fourth(x)); | ||
| 179 | } | ||
| 180 | Poll::Pending | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | // ==================================================================== | ||
| 185 | |||
| 186 | /// Future for the [`select_all`] function. | ||
| 187 | #[derive(Debug)] | ||
| 188 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 189 | pub struct SelectAll<Fut, const N: usize> { | ||
| 190 | inner: [Fut; N], | ||
| 191 | } | ||
| 192 | |||
| 193 | /// Creates a new future which will select over a list of futures. | ||
| 194 | /// | ||
| 195 | /// The returned future will wait for any future within `iter` to be ready. Upon | ||
| 196 | /// completion the item resolved will be returned, along with the index of the | ||
| 197 | /// future that was ready. | ||
| 198 | /// | ||
| 199 | /// # Panics | ||
| 200 | /// | ||
| 201 | /// This function will panic if the array specified contains no items. | ||
| 202 | pub fn select_all<Fut: Future, const N: usize>(arr: [Fut; N]) -> SelectAll<Fut, N> { | ||
| 203 | assert!(N > 0); | ||
| 204 | SelectAll { inner: arr } | ||
| 205 | } | ||
| 206 | |||
| 207 | impl<Fut: Future, const N: usize> Future for SelectAll<Fut, N> { | ||
| 208 | type Output = (Fut::Output, usize); | ||
| 209 | |||
| 210 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 211 | // Safety: Since `self` is pinned, `inner` cannot move. Since `inner` cannot move, | ||
| 212 | // its elements also cannot move. Therefore it is safe to access `inner` and pin | ||
| 213 | // references to the contained futures. | ||
| 214 | let item = unsafe { | ||
| 215 | self.get_unchecked_mut() | ||
| 216 | .inner | ||
| 217 | .iter_mut() | ||
| 218 | .enumerate() | ||
| 219 | .find_map(|(i, f)| match Pin::new_unchecked(f).poll(cx) { | ||
| 220 | Poll::Pending => None, | ||
| 221 | Poll::Ready(e) => Some((i, e)), | ||
| 222 | }) | ||
| 223 | }; | ||
| 224 | |||
| 225 | match item { | ||
| 226 | Some((idx, res)) => Poll::Ready((res, idx)), | ||
| 227 | None => Poll::Pending, | ||
| 228 | } | ||
| 229 | } | ||
| 230 | } | ||
diff --git a/embassy-futures/src/yield_now.rs b/embassy-futures/src/yield_now.rs new file mode 100644 index 000000000..1ebecb916 --- /dev/null +++ b/embassy-futures/src/yield_now.rs | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | use core::future::Future; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use core::task::{Context, Poll}; | ||
| 4 | |||
| 5 | /// Yield from the current task once, allowing other tasks to run. | ||
| 6 | pub fn yield_now() -> impl Future<Output = ()> { | ||
| 7 | YieldNowFuture { yielded: false } | ||
| 8 | } | ||
| 9 | |||
| 10 | struct YieldNowFuture { | ||
| 11 | yielded: bool, | ||
| 12 | } | ||
| 13 | |||
| 14 | impl Future for YieldNowFuture { | ||
| 15 | type Output = (); | ||
| 16 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 17 | if self.yielded { | ||
| 18 | Poll::Ready(()) | ||
| 19 | } else { | ||
| 20 | self.yielded = true; | ||
| 21 | cx.waker().wake_by_ref(); | ||
| 22 | Poll::Pending | ||
| 23 | } | ||
| 24 | } | ||
| 25 | } | ||
