Skip to content

Commit 68f7a10

Browse files
author
Stjepan Glavina
committed
Add set_interval and set_interval_at
1 parent 75316e2 commit 68f7a10

File tree

1 file changed

+86
-24
lines changed

1 file changed

+86
-24
lines changed

src/lib.rs

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! * [`Async`], an adapter for standard networking types (and [many other] types) to use in
66
//! async programs.
7-
//! * [`Timer`], a future that expires at a point in time.
7+
//! * [`Timer`], a future or stream that emits timed events.
88
//!
99
//! For concrete async networking types built on top of this crate, see [`async-net`].
1010
//!
@@ -85,14 +85,16 @@ mod reactor;
8585

8686
pub use driver::block_on;
8787

88-
/// Use Duration::MAX once duration_constants are stabilized.
88+
/// Use `Duration::MAX` once `duration_constants` are stabilized.
8989
fn duration_max() -> Duration {
9090
Duration::new(u64::MAX, 1_000_000_000 - 1)
9191
}
9292

93-
/// A future that expires at a point in time.
93+
/// A future or stream that emits timed events.
9494
///
95-
/// Timers are futures that output the [`Instant`] at which they fired.
95+
/// Timers are futures that output a single [`Instant`] when they fire.
96+
///
97+
/// Timers are also streams that can output [`Instant`]s periodically.
9698
///
9799
/// # Examples
98100
///
@@ -130,15 +132,15 @@ pub struct Timer {
130132
/// When this field is set to `None`, this timer is not registered in the reactor.
131133
id_and_waker: Option<(usize, Waker)>,
132134

133-
/// When this timer fires.
135+
/// The next instant at which this timer fires.
134136
when: Instant,
135137

136138
/// The period.
137139
period: Duration,
138140
}
139141

140142
impl Timer {
141-
/// Creates a timer that expires after the given duration of time.
143+
/// Creates a timer that emits an event once after the given duration of time.
142144
///
143145
/// # Examples
144146
///
@@ -154,7 +156,7 @@ impl Timer {
154156
Timer::at(Instant::now() + duration)
155157
}
156158

157-
/// Creates a timer that expires at the given time instant.
159+
/// Creates a timer that emits an event once at the given time instant.
158160
///
159161
/// # Examples
160162
///
@@ -173,7 +175,48 @@ impl Timer {
173175
Timer::interval_at(instant, duration_max())
174176
}
175177

176-
/// Sets the timer to expire after the new duration of time.
178+
/// Creates a timer that emits events periodically.
179+
///
180+
/// # Examples
181+
///
182+
/// ```
183+
/// use async_io::Timer;
184+
/// use futures_lite::StreamExt;
185+
/// use std::time::{Duration, Instant};
186+
///
187+
/// # futures_lite::future::block_on(async {
188+
/// let period = Duration::from_secs(1);
189+
/// Timer::interval(period).next().await;
190+
/// # });
191+
/// ```
192+
pub fn interval(period: Duration) -> Timer {
193+
Timer::interval_at(Instant::now() + period, period)
194+
}
195+
196+
/// Creates a timer that emits events periodically, starting at `start`.
197+
///
198+
/// # Examples
199+
///
200+
/// ```
201+
/// use async_io::Timer;
202+
/// use futures_lite::StreamExt;
203+
/// use std::time::{Duration, Instant};
204+
///
205+
/// # futures_lite::future::block_on(async {
206+
/// let start = Instant::now();
207+
/// let period = Duration::from_secs(1);
208+
/// Timer::interval_at(start, period).next().await;
209+
/// # });
210+
/// ```
211+
pub fn interval_at(start: Instant, period: Duration) -> Timer {
212+
Timer {
213+
id_and_waker: None,
214+
when: start,
215+
period,
216+
}
217+
}
218+
219+
/// Sets the timer to emit an en event once after the given duration of time.
177220
///
178221
/// Note that resetting a timer is different from creating a new timer because
179222
/// [`set_after()`][`Timer::set_after()`] does not remove the waker associated with the task
@@ -194,10 +237,10 @@ impl Timer {
194237
self.set_at(Instant::now() + duration);
195238
}
196239

197-
/// Sets the timer to expire at the new time instant.
240+
/// Sets the timer to emit an event once at the given time instant.
198241
///
199242
/// Note that resetting a timer is different from creating a new timer because
200-
/// [`set_after()`][`Timer::set_after()`] does not remove the waker associated with the task
243+
/// [`set_at()`][`Timer::set_at()`] does not remove the waker associated with the task
201244
/// that is polling the timer.
202245
///
203246
/// # Examples
@@ -229,7 +272,11 @@ impl Timer {
229272
}
230273
}
231274

232-
/// Creates a timer that ticks every period.
275+
/// Sets the timer to emit events periodically.
276+
///
277+
/// Note that resetting a timer is different from creating a new timer because
278+
/// [`set_interval()`][`Timer::set_interval()`] does not remove the waker associated with the
279+
/// task that is polling the timer.
233280
///
234281
/// # Examples
235282
///
@@ -239,15 +286,21 @@ impl Timer {
239286
/// use std::time::{Duration, Instant};
240287
///
241288
/// # futures_lite::future::block_on(async {
242-
/// let period = Duration::from_secs(1);
243-
/// Timer::interval(period).next().await;
289+
/// let mut t = Timer::after(Duration::from_secs(1));
290+
///
291+
/// let period = Duration::from_secs(2);
292+
/// t.set_interval(period);
244293
/// # });
245294
/// ```
246-
pub fn interval(period: Duration) -> Timer {
247-
Timer::interval_at(Instant::now() + period, period)
295+
pub fn set_interval(&mut self, period: Duration) {
296+
self.set_interval_at(Instant::now() + period, period);
248297
}
249298

250-
/// Creates a timer that ticks every period, starting at `start`.
299+
/// Sets the timer to emit events periodically, starting at `start`.
300+
///
301+
/// Note that resetting a timer is different from creating a new timer because
302+
/// [`set_interval_at()`][`Timer::set_interval_at()`] does not remove the waker associated with
303+
/// the task that is polling the timer.
251304
///
252305
/// # Examples
253306
///
@@ -257,16 +310,25 @@ impl Timer {
257310
/// use std::time::{Duration, Instant};
258311
///
259312
/// # futures_lite::future::block_on(async {
260-
/// let now = Instant::now();
261-
/// let period = Duration::from_secs(1);
262-
/// Timer::interval_at(now, period).next().await;
313+
/// let mut t = Timer::after(Duration::from_secs(1));
314+
///
315+
/// let start = Instant::now();
316+
/// let period = Duration::from_secs(2);
317+
/// t.set_interval_at(start, period);
263318
/// # });
264319
/// ```
265-
pub fn interval_at(start: Instant, period: Duration) -> Timer {
266-
Timer {
267-
id_and_waker: None,
268-
when: start,
269-
period: period,
320+
pub fn set_interval_at(&mut self, start: Instant, period: Duration) {
321+
if let Some((id, _)) = self.id_and_waker.as_ref() {
322+
// Deregister the timer from the reactor.
323+
Reactor::get().remove_timer(self.when, *id);
324+
}
325+
326+
self.when = start;
327+
self.period = period;
328+
329+
if let Some((id, waker)) = self.id_and_waker.as_mut() {
330+
// Re-register the timer with the new timeout.
331+
*id = Reactor::get().insert_timer(self.when, waker);
270332
}
271333
}
272334
}

0 commit comments

Comments
 (0)