diff options
| -rw-r--r-- | embassy-traits/src/delay.rs | 3 | ||||
| -rw-r--r-- | embassy/src/executor/timer.rs | 73 |
2 files changed, 76 insertions, 0 deletions
diff --git a/embassy-traits/src/delay.rs b/embassy-traits/src/delay.rs index b893ee4a3..1e763350b 100644 --- a/embassy-traits/src/delay.rs +++ b/embassy-traits/src/delay.rs | |||
| @@ -4,6 +4,9 @@ use core::pin::Pin; | |||
| 4 | pub trait Delay { | 4 | pub trait Delay { |
| 5 | type DelayFuture<'a>: Future<Output = ()> + 'a; | 5 | type DelayFuture<'a>: Future<Output = ()> + 'a; |
| 6 | 6 | ||
| 7 | /// Future that completes after now + millis | ||
| 7 | fn delay_ms<'a>(self: Pin<&'a mut Self>, millis: u64) -> Self::DelayFuture<'a>; | 8 | fn delay_ms<'a>(self: Pin<&'a mut Self>, millis: u64) -> Self::DelayFuture<'a>; |
| 9 | |||
| 10 | /// Future that completes after now + micros | ||
| 8 | fn delay_us<'a>(self: Pin<&'a mut Self>, micros: u64) -> Self::DelayFuture<'a>; | 11 | fn delay_us<'a>(self: Pin<&'a mut Self>, micros: u64) -> Self::DelayFuture<'a>; |
| 9 | } | 12 | } |
diff --git a/embassy/src/executor/timer.rs b/embassy/src/executor/timer.rs index 256ecf665..541f96f59 100644 --- a/embassy/src/executor/timer.rs +++ b/embassy/src/executor/timer.rs | |||
| @@ -7,6 +7,7 @@ use futures::Stream; | |||
| 7 | use super::raw; | 7 | use super::raw; |
| 8 | use crate::time::{Duration, Instant}; | 8 | use crate::time::{Duration, Instant}; |
| 9 | 9 | ||
| 10 | /// Delay abstraction using embassy's clock. | ||
| 10 | pub struct Delay { | 11 | pub struct Delay { |
| 11 | _data: PhantomData<bool>, | 12 | _data: PhantomData<bool>, |
| 12 | } | 13 | } |
| @@ -30,12 +31,14 @@ impl crate::traits::delay::Delay for Delay { | |||
| 30 | } | 31 | } |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 34 | /// A future that completes at a specified [Instant](struct.Instant.html). | ||
| 33 | pub struct Timer { | 35 | pub struct Timer { |
| 34 | expires_at: Instant, | 36 | expires_at: Instant, |
| 35 | yielded_once: bool, | 37 | yielded_once: bool, |
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | impl Timer { | 40 | impl Timer { |
| 41 | /// Expire at specified [Instant](struct.Instant.html) | ||
| 39 | pub fn at(expires_at: Instant) -> Self { | 42 | pub fn at(expires_at: Instant) -> Self { |
| 40 | Self { | 43 | Self { |
| 41 | expires_at, | 44 | expires_at, |
| @@ -43,6 +46,26 @@ impl Timer { | |||
| 43 | } | 46 | } |
| 44 | } | 47 | } |
| 45 | 48 | ||
| 49 | /// Expire after specified [Duration](struct.Duration.html). | ||
| 50 | /// This can be used as a `sleep` abstraction. | ||
| 51 | /// | ||
| 52 | /// Example: | ||
| 53 | /// ``` no_run | ||
| 54 | /// # #![feature(trait_alias)] | ||
| 55 | /// # #![feature(min_type_alias_impl_trait)] | ||
| 56 | /// # #![feature(impl_trait_in_bindings)] | ||
| 57 | /// # #![feature(type_alias_impl_trait)] | ||
| 58 | /// # | ||
| 59 | /// # fn foo() {} | ||
| 60 | /// use embassy::executor::task; | ||
| 61 | /// use embassy::time::{Duration, Timer}; | ||
| 62 | /// | ||
| 63 | /// #[task] | ||
| 64 | /// async fn demo_sleep_seconds() { | ||
| 65 | /// // suspend this task for one second. | ||
| 66 | /// Timer::after(Duration::from_secs(1)).await; | ||
| 67 | /// } | ||
| 68 | /// ``` | ||
| 46 | pub fn after(duration: Duration) -> Self { | 69 | pub fn after(duration: Duration) -> Self { |
| 47 | Self { | 70 | Self { |
| 48 | expires_at: Instant::now() + duration, | 71 | expires_at: Instant::now() + duration, |
| @@ -66,12 +89,62 @@ impl Future for Timer { | |||
| 66 | } | 89 | } |
| 67 | } | 90 | } |
| 68 | 91 | ||
| 92 | /// Asynchronous stream that yields every Duration, indefinitely. | ||
| 93 | /// | ||
| 94 | /// This stream will tick at uniform intervals, even if blocking work is performed between ticks. | ||
| 95 | /// | ||
| 96 | /// For instance, consider the following code fragment. | ||
| 97 | /// ``` no_run | ||
| 98 | /// # #![feature(trait_alias)] | ||
| 99 | /// # #![feature(min_type_alias_impl_trait)] | ||
| 100 | /// # #![feature(impl_trait_in_bindings)] | ||
| 101 | /// # #![feature(type_alias_impl_trait)] | ||
| 102 | /// # | ||
| 103 | /// use embassy::executor::task; | ||
| 104 | /// use embassy::time::{Duration, Timer}; | ||
| 105 | /// # fn foo() {} | ||
| 106 | /// | ||
| 107 | /// #[task] | ||
| 108 | /// async fn ticker_example_0() { | ||
| 109 | /// loop { | ||
| 110 | /// foo(); | ||
| 111 | /// Timer::after(Duration::from_secs(1)).await; | ||
| 112 | /// } | ||
| 113 | /// } | ||
| 114 | /// ``` | ||
| 115 | /// | ||
| 116 | /// This fragment will not call `foo` every second. | ||
| 117 | /// Instead, it will call it every second + the time it took to previously call `foo`. | ||
| 118 | /// | ||
| 119 | /// Example using ticker, which will consistently call `foo` once a second. | ||
| 120 | /// | ||
| 121 | /// ``` no_run | ||
| 122 | /// # #![feature(trait_alias)] | ||
| 123 | /// # #![feature(min_type_alias_impl_trait)] | ||
| 124 | /// # #![feature(impl_trait_in_bindings)] | ||
| 125 | /// # #![feature(type_alias_impl_trait)] | ||
| 126 | /// # | ||
| 127 | /// use embassy::executor::task; | ||
| 128 | /// use embassy::time::{Duration, Ticker}; | ||
| 129 | /// use futures::StreamExt; | ||
| 130 | /// # fn foo(){} | ||
| 131 | /// | ||
| 132 | /// #[task] | ||
| 133 | /// async fn ticker_example_1() { | ||
| 134 | /// let mut ticker = Ticker::every(Duration::from_secs(1)); | ||
| 135 | /// loop { | ||
| 136 | /// foo(); | ||
| 137 | /// ticker.next().await; | ||
| 138 | /// } | ||
| 139 | /// } | ||
| 140 | /// ``` | ||
| 69 | pub struct Ticker { | 141 | pub struct Ticker { |
| 70 | expires_at: Instant, | 142 | expires_at: Instant, |
| 71 | duration: Duration, | 143 | duration: Duration, |
| 72 | } | 144 | } |
| 73 | 145 | ||
| 74 | impl Ticker { | 146 | impl Ticker { |
| 147 | /// Creates a new ticker that ticks at the specified duration interval. | ||
| 75 | pub fn every(duration: Duration) -> Self { | 148 | pub fn every(duration: Duration) -> Self { |
| 76 | let expires_at = Instant::now() + duration; | 149 | let expires_at = Instant::now() + duration; |
| 77 | Self { | 150 | Self { |
