diff options
Diffstat (limited to 'embassy-time/src/timer.rs')
| -rw-r--r-- | embassy-time/src/timer.rs | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs index fe0e93951..763bfdeeb 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 | /// |
| @@ -204,7 +210,7 @@ impl Ticker { | |||
| 204 | self.expires_at += dur; | 210 | self.expires_at += dur; |
| 205 | Poll::Ready(()) | 211 | Poll::Ready(()) |
| 206 | } else { | 212 | } else { |
| 207 | schedule_wake(self.expires_at, cx.waker()); | 213 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 208 | Poll::Pending | 214 | Poll::Pending |
| 209 | } | 215 | } |
| 210 | }) | 216 | }) |
| @@ -221,7 +227,7 @@ impl Stream for Ticker { | |||
| 221 | self.expires_at += dur; | 227 | self.expires_at += dur; |
| 222 | Poll::Ready(Some(())) | 228 | Poll::Ready(Some(())) |
| 223 | } else { | 229 | } else { |
| 224 | schedule_wake(self.expires_at, cx.waker()); | 230 | embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker()); |
| 225 | Poll::Pending | 231 | Poll::Pending |
| 226 | } | 232 | } |
| 227 | } | 233 | } |
| @@ -233,11 +239,3 @@ impl FusedStream for Ticker { | |||
| 233 | false | 239 | false |
| 234 | } | 240 | } |
| 235 | } | 241 | } |
| 236 | |||
| 237 | extern "Rust" { | ||
| 238 | fn _embassy_time_schedule_wake(at: Instant, waker: &Waker); | ||
| 239 | } | ||
| 240 | |||
| 241 | fn schedule_wake(at: Instant, waker: &Waker) { | ||
| 242 | unsafe { _embassy_time_schedule_wake(at, waker) } | ||
| 243 | } | ||
