mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-28 00:00:11 +02:00
Provide a timer implementation (#249)
This patch adds a new crate: tokio-timer. This crate provides an efficient timer implemeentation designed for use in Tokio based applications. The timer users a hierarchical hashed timer wheel algorithm with six levels, each having 64 slots. This allows the timer to have a resolution of 1ms while maintaining O(1) complexity for insert, removal, and firing of timeouts. There already exists a tokio-timer crate. This is a complete rewrite which solves the outstanding problems with the existing tokio-timer library. Closes #146.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
use Error;
|
||||
use timer::{Handle, Entry};
|
||||
|
||||
use futures::Poll;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
/// Registration with a timer.
|
||||
///
|
||||
/// The association between a `Sleep` instance and a timer is done lazily in
|
||||
/// `poll`
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Registration {
|
||||
entry: Arc<Entry>,
|
||||
}
|
||||
|
||||
impl Registration {
|
||||
pub fn new(deadline: Instant) -> Registration {
|
||||
fn is_send<T: Send + Sync>() {}
|
||||
is_send::<Registration>();
|
||||
|
||||
match Handle::try_current() {
|
||||
Ok(handle) => Registration::new_with_handle(deadline, handle),
|
||||
Err(_) => Registration::new_error(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_handle(deadline: Instant, handle: Handle) -> Registration {
|
||||
let inner = match handle.inner() {
|
||||
Some(inner) => inner,
|
||||
None => return Registration::new_error(),
|
||||
};
|
||||
|
||||
// Increment the number of active timeouts
|
||||
if inner.increment().is_err() {
|
||||
return Registration::new_error();
|
||||
}
|
||||
|
||||
let when = inner.normalize_deadline(deadline);
|
||||
|
||||
if when <= inner.elapsed() {
|
||||
// The deadline has already elapsed, ther eis no point creating the
|
||||
// structures.
|
||||
return Registration {
|
||||
entry: Arc::new(Entry::new_elapsed(handle)),
|
||||
};
|
||||
}
|
||||
|
||||
let entry = Arc::new(Entry::new(when, handle));
|
||||
|
||||
if inner.queue(&entry).is_err() {
|
||||
// The timer has shutdown, transition the entry to the error state.
|
||||
entry.error();
|
||||
}
|
||||
|
||||
Registration { entry }
|
||||
}
|
||||
|
||||
pub fn reset(&self, deadline: Instant) {
|
||||
Entry::reset(&self.entry, deadline);
|
||||
}
|
||||
|
||||
fn new_error() -> Registration {
|
||||
let entry = Arc::new(Entry::new_error());
|
||||
Registration { entry }
|
||||
}
|
||||
|
||||
pub fn is_elapsed(&self) -> bool {
|
||||
self.entry.is_elapsed()
|
||||
}
|
||||
|
||||
pub fn poll_elapsed(&self) -> Poll<(), Error> {
|
||||
self.entry.poll_elapsed()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Registration {
|
||||
fn drop(&mut self) {
|
||||
Entry::cancel(&self.entry);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user