diff options
| author | Frostie314159 <[email protected]> | 2024-03-31 20:48:05 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-03-31 20:48:05 +0200 |
| commit | 67c9cc2c4b886e6962ecdd6eff8794b14c1accdc (patch) | |
| tree | f176ab269949d26f48e04c950cebc5489bae8c56 /embassy-time/src/timer.rs | |
| parent | a2f9aa592ec61beb247065003016515f0d423c13 (diff) | |
| parent | 6634cc90bcd3eb25b64712688920f383584b2964 (diff) | |
Merge branch 'embassy-rs:main' into ticker_send_sync
Diffstat (limited to 'embassy-time/src/timer.rs')
| -rw-r--r-- | embassy-time/src/timer.rs | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs index a123c1d01..757c3ff00 100644 --- a/embassy-time/src/timer.rs +++ b/embassy-time/src/timer.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | use core::future::{poll_fn, Future}; | 1 | use core::future::{poll_fn, Future}; |
| 2 | use core::pin::Pin; | 2 | use core::pin::Pin; |
| 3 | use core::task::{Context, Poll, Waker}; | 3 | use core::task::{Context, Poll}; |
| 4 | 4 | ||
| 5 | use futures_util::future::{select, Either}; | 5 | use futures_util::future::{select, Either}; |
| 6 | use futures_util::stream::FusedStream; | 6 | use futures_util::stream::FusedStream; |
| @@ -8,7 +8,7 @@ use futures_util::{pin_mut, Stream}; | |||
| 8 | 8 | ||
| 9 | use crate::{Duration, Instant}; | 9 | use crate::{Duration, Instant}; |
| 10 | 10 | ||
| 11 | /// Error returned by [`with_timeout`] on timeout. | 11 | /// Error returned by [`with_timeout`] and [`with_deadline`] on timeout. |
| 12 | #[derive(Debug, Clone, PartialEq, Eq)] | 12 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 14 | pub struct TimeoutError; | 14 | pub struct TimeoutError; |
| @@ -26,6 +26,19 @@ pub async fn with_timeout<F: Future>(timeout: Duration, fut: F) -> Result<F::Out | |||
| 26 | } | 26 | } |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | /// Runs a given future with a deadline time. | ||
| 30 | /// | ||
| 31 | /// If the future completes before the deadline, its output is returned. Otherwise, on timeout, | ||
| 32 | /// work on the future is stopped (`poll` is no longer called), the future is dropped and `Err(TimeoutError)` is returned. | ||
| 33 | pub async fn with_deadline<F: Future>(at: Instant, fut: F) -> Result<F::Output, TimeoutError> { | ||
| 34 | let timeout_fut = Timer::at(at); | ||
| 35 | pin_mut!(fut); | ||
| 36 | match select(fut, timeout_fut).await { | ||
| 37 | Either::Left((r, _)) => Ok(r), | ||
| 38 | Either::Right(_) => Err(TimeoutError), | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 29 | /// A future that completes at a specified [Instant](struct.Instant.html). | 42 | /// A future that completes at a specified [Instant](struct.Instant.html). |
| 30 | #[must_use = "futures do nothing unless you `.await` or poll them"] | 43 | #[must_use = "futures do nothing unless you `.await` or poll them"] |
| 31 | pub struct Timer { | 44 | pub struct Timer { |
| @@ -47,9 +60,6 @@ impl Timer { | |||
| 47 | /// | 60 | /// |
| 48 | /// Example: | 61 | /// Example: |
| 49 | /// ``` no_run | 62 | /// ``` no_run |
| 50 | /// # #![feature(type_alias_impl_trait)] | ||
| 51 | /// # | ||
| 52 | /// # fn foo() {} | ||
| 53 | /// use embassy_time::{Duration, Timer}; | 63 | /// use embassy_time::{Duration, Timer}; |
| 54 | /// | 64 | /// |
| 55 | /// #[embassy_executor::task] | 65 | /// #[embassy_executor::task] |
| @@ -119,7 +129,7 @@ impl Future for Timer { | |||
| 119 | if self.yielded_once && self.expires_at <= Instant::now() { | 129 | if self.yielded_once && self.expires_at <= Instant::now() { |
| 120 | Poll::Ready(()) | 130 | Poll::Ready(()) |
| 121 | } else { | 131 | } else { |
| 122 | schedule_wake(self.expires_at, cx.waker()); | 132 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 123 | self.yielded_once = true; | 133 | self.yielded_once = true; |
| 124 | Poll::Pending | 134 | Poll::Pending |
| 125 | } | 135 | } |
| @@ -132,8 +142,6 @@ impl Future for Timer { | |||
| 132 | /// | 142 | /// |
| 133 | /// For instance, consider the following code fragment. | 143 | /// For instance, consider the following code fragment. |
| 134 | /// ``` no_run | 144 | /// ``` no_run |
| 135 | /// # #![feature(type_alias_impl_trait)] | ||
| 136 | /// # | ||
| 137 | /// use embassy_time::{Duration, Timer}; | 145 | /// use embassy_time::{Duration, Timer}; |
| 138 | /// # fn foo() {} | 146 | /// # fn foo() {} |
| 139 | /// | 147 | /// |
| @@ -152,8 +160,6 @@ impl Future for Timer { | |||
| 152 | /// Example using ticker, which will consistently call `foo` once a second. | 160 | /// Example using ticker, which will consistently call `foo` once a second. |
| 153 | /// | 161 | /// |
| 154 | /// ``` no_run | 162 | /// ``` no_run |
| 155 | /// # #![feature(type_alias_impl_trait)] | ||
| 156 | /// # | ||
| 157 | /// use embassy_time::{Duration, Ticker}; | 163 | /// use embassy_time::{Duration, Ticker}; |
| 158 | /// # fn foo(){} | 164 | /// # fn foo(){} |
| 159 | /// | 165 | /// |
| @@ -184,6 +190,18 @@ impl Ticker { | |||
| 184 | self.expires_at = Instant::now() + self.duration; | 190 | self.expires_at = Instant::now() + self.duration; |
| 185 | } | 191 | } |
| 186 | 192 | ||
| 193 | /// Reset the ticker at the deadline. | ||
| 194 | /// If the deadline is in the past, the ticker will fire instantly. | ||
| 195 | pub fn reset_at(&mut self, deadline: Instant) { | ||
| 196 | self.expires_at = deadline + self.duration; | ||
| 197 | } | ||
| 198 | |||
| 199 | /// Resets the ticker, after the specified duration has passed. | ||
| 200 | /// If the specified duration is zero, the next tick will be after the duration of the ticker. | ||
| 201 | pub fn reset_after(&mut self, after: Duration) { | ||
| 202 | self.expires_at = Instant::now() + after + self.duration; | ||
| 203 | } | ||
| 204 | |||
| 187 | /// Waits for the next tick. | 205 | /// Waits for the next tick. |
| 188 | pub fn next(&mut self) -> impl Future<Output = ()> + Send + Sync + '_ { | 206 | pub fn next(&mut self) -> impl Future<Output = ()> + Send + Sync + '_ { |
| 189 | poll_fn(|cx| { | 207 | poll_fn(|cx| { |
| @@ -192,7 +210,7 @@ impl Ticker { | |||
| 192 | self.expires_at += dur; | 210 | self.expires_at += dur; |
| 193 | Poll::Ready(()) | 211 | Poll::Ready(()) |
| 194 | } else { | 212 | } else { |
| 195 | schedule_wake(self.expires_at, cx.waker()); | 213 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 196 | Poll::Pending | 214 | Poll::Pending |
| 197 | } | 215 | } |
| 198 | }) | 216 | }) |
| @@ -209,7 +227,7 @@ impl Stream for Ticker { | |||
| 209 | self.expires_at += dur; | 227 | self.expires_at += dur; |
| 210 | Poll::Ready(Some(())) | 228 | Poll::Ready(Some(())) |
| 211 | } else { | 229 | } else { |
| 212 | schedule_wake(self.expires_at, cx.waker()); | 230 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 213 | Poll::Pending | 231 | Poll::Pending |
| 214 | } | 232 | } |
| 215 | } | 233 | } |
| @@ -221,11 +239,3 @@ impl FusedStream for Ticker { | |||
| 221 | false | 239 | false |
| 222 | } | 240 | } |
| 223 | } | 241 | } |
| 224 | |||
| 225 | extern "Rust" { | ||
| 226 | fn _embassy_time_schedule_wake(at: Instant, waker: &Waker); | ||
| 227 | } | ||
| 228 | |||
| 229 | fn schedule_wake(at: Instant, waker: &Waker) { | ||
| 230 | unsafe { _embassy_time_schedule_wake(at, waker) } | ||
| 231 | } | ||
