aboutsummaryrefslogtreecommitdiff
path: root/embassy-time/src/timer.rs
diff options
context:
space:
mode:
authorFrostie314159 <[email protected]>2024-03-31 20:48:05 +0200
committerGitHub <[email protected]>2024-03-31 20:48:05 +0200
commit67c9cc2c4b886e6962ecdd6eff8794b14c1accdc (patch)
treef176ab269949d26f48e04c950cebc5489bae8c56 /embassy-time/src/timer.rs
parenta2f9aa592ec61beb247065003016515f0d423c13 (diff)
parent6634cc90bcd3eb25b64712688920f383584b2964 (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.rs50
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 @@
1use core::future::{poll_fn, Future}; 1use core::future::{poll_fn, Future};
2use core::pin::Pin; 2use core::pin::Pin;
3use core::task::{Context, Poll, Waker}; 3use core::task::{Context, Poll};
4 4
5use futures_util::future::{select, Either}; 5use futures_util::future::{select, Either};
6use futures_util::stream::FusedStream; 6use futures_util::stream::FusedStream;
@@ -8,7 +8,7 @@ use futures_util::{pin_mut, Stream};
8 8
9use crate::{Duration, Instant}; 9use 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))]
14pub struct TimeoutError; 14pub 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.
33pub 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"]
31pub struct Timer { 44pub 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
225extern "Rust" {
226 fn _embassy_time_schedule_wake(at: Instant, waker: &Waker);
227}
228
229fn schedule_wake(at: Instant, waker: &Waker) {
230 unsafe { _embassy_time_schedule_wake(at, waker) }
231}