mirror of https://github.com/stjepang/smol
Add Timer::{reset_at, reset_after}
This commit is contained in:
parent
ee25d12cac
commit
94027529a4
|
@ -168,6 +168,19 @@ impl Reactor {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reset a timer to a new Instant.
|
||||
pub fn reset_timer(&self, when: Instant, id: usize, new: Instant) {
|
||||
// Push a reset operation.
|
||||
while self.timer_ops.push(TimerOp::Reset(when, id, new)).is_err() {
|
||||
// Fire timers to drain the queue.
|
||||
self.fire_timers();
|
||||
}
|
||||
// Notify if the new instant is sooner than the original.
|
||||
if new < when {
|
||||
self.timer_event.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to lock the reactor.
|
||||
pub fn try_lock(&self) -> Option<ReactorLock<'_>> {
|
||||
self.events.try_lock().map(|events| {
|
||||
|
@ -202,6 +215,11 @@ impl Reactor {
|
|||
Ok(TimerOp::Remove(when, id)) => {
|
||||
timers.remove(&(when, id));
|
||||
}
|
||||
Ok(TimerOp::Reset(when, id, new)) => {
|
||||
if let Some(waker) = timers.remove(&(when, id)) {
|
||||
timers.insert((new, id), waker);
|
||||
}
|
||||
}
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
|
@ -312,6 +330,7 @@ impl ReactorLock<'_> {
|
|||
enum TimerOp {
|
||||
Insert(Instant, usize, Waker),
|
||||
Remove(Instant, usize),
|
||||
Reset(/* original */ Instant, usize, /* new */ Instant),
|
||||
}
|
||||
|
||||
/// A registered source of I/O events.
|
||||
|
|
16
src/timer.rs
16
src/timer.rs
|
@ -106,6 +106,22 @@ impl Timer {
|
|||
let id = None;
|
||||
Timer { id, when }
|
||||
}
|
||||
|
||||
/// Reset the timer to fire at the specified instant.
|
||||
pub fn reset_at(&mut self, when: Instant) {
|
||||
match self.id {
|
||||
None => {}
|
||||
Some(id) => {
|
||||
Reactor::get().reset_timer(self.when, id, when);
|
||||
self.when = when;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset timer to fire after the specified duration of time.
|
||||
pub fn reset_after(&mut self, dur: Duration) {
|
||||
self.reset_at(Instant::now() + dur);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Timer {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use futures::prelude::*;
|
||||
use smol::{self, Timer};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
#[test]
|
||||
|
@ -23,3 +25,27 @@ fn timer_after() {
|
|||
|
||||
assert!(before.elapsed() >= Duration::from_secs(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn timer_reset() {
|
||||
smol::run(async move {
|
||||
let start = Instant::now();
|
||||
let t = Arc::new(Mutex::new(Timer::after(Duration::from_secs(10))));
|
||||
let t1 = t.clone();
|
||||
// Use another thread instead of smol::Task to avoid any interference
|
||||
// with the runtime.
|
||||
std::thread::spawn(move || {
|
||||
std::thread::sleep(Duration::from_millis(500));
|
||||
t1.lock().unwrap().reset_after(Duration::from_secs(1));
|
||||
});
|
||||
smol::Task::local(futures::future::poll_fn(move |cx| {
|
||||
t.lock().unwrap().poll_unpin(cx)
|
||||
}))
|
||||
.await;
|
||||
|
||||
let e = start.elapsed();
|
||||
|
||||
assert!(e >= Duration::from_millis(1300));
|
||||
assert!(e < Duration::from_millis(1700));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue