timer: finish updating timer (#1222)

* timer: restructure feature flags
* update timer tests
* Add `async-traits` to CI

This also disables a buggy `threadpool` test. This test should be fixed in the future.

Refs #1225
This commit is contained in:
Carl Lerche
2019-06-30 08:48:53 -07:00
committed by GitHub
parent 8e7d8af588
commit b2c777846e
27 changed files with 786 additions and 755 deletions
+3 -4
View File
@@ -4,7 +4,6 @@ use std::cell::Cell;
use std::fmt;
use std::sync::Arc;
use std::time::Instant;
use tokio_executor::Enter;
/// A handle to a source of time.
///
@@ -108,9 +107,9 @@ impl fmt::Debug for Clock {
/// # Panics
///
/// This function panics if there already is a default clock set.
pub fn with_default<F, R>(clock: &Clock, enter: &mut Enter, f: F) -> R
pub fn with_default<F, R>(clock: &Clock, f: F) -> R
where
F: FnOnce(&mut Enter) -> R,
F: FnOnce() -> R,
{
CLOCK.with(|cell| {
assert!(
@@ -132,6 +131,6 @@ where
cell.set(Some(clock as *const Clock));
f(enter)
f()
})
}
+1 -1
View File
@@ -74,7 +74,7 @@ impl Delay {
}
// Used by `Timeout<Stream>`
#[cfg(feature = "timeout-stream")]
#[cfg(feature = "async-traits")]
pub(crate) fn reset_timeout(&mut self) {
self.registration.reset_timeout();
}
+33 -17
View File
@@ -8,7 +8,7 @@ use crate::clock::now;
use crate::timer::Handle;
use crate::wheel::{self, Wheel};
use crate::{Delay, Error};
use futures_core::Stream;
use slab::Slab;
use std::cmp;
use std::future::Future;
@@ -347,6 +347,34 @@ impl<T> DelayQueue<T> {
Key::new(key)
}
/// TODO: Dox... also is the fn signature correct?
pub fn poll_next(
&mut self,
cx: &mut task::Context<'_>,
) -> Poll<Option<Result<Expired<T>, Error>>> {
let item = ready!(self.poll_idx(cx));
Poll::Ready(item.map(|result| {
result.map(|idx| {
let data = self.slab.remove(idx);
debug_assert!(data.next.is_none());
debug_assert!(data.prev.is_none());
Expired {
key: Key::new(idx),
data: data.inner,
deadline: self.start + Duration::from_millis(data.when),
}
})
}))
}
/// TODO: Dox... also is the fn signature correct?
pub async fn next(&mut self) -> Option<Result<Expired<T>, Error>> {
use async_util::future::poll_fn;
poll_fn(|cx| self.poll_next(cx)).await
}
/// Insert `value` into the queue set to expire after the requested duration
/// elapses.
///
@@ -696,26 +724,14 @@ impl<T> DelayQueue<T> {
// We never put `T` in a `Pin`...
impl<T> Unpin for DelayQueue<T> {}
impl<T> Stream for DelayQueue<T> {
#[cfg(feature = "async-traits")]
impl<T> futures_core::Stream for DelayQueue<T> {
// DelayQueue seems much more specific, where a user may care that it
// has reached capacity, so return those errors instead of panicking.
type Item = Result<Expired<T>, Error>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
let item = ready!(self.poll_idx(cx));
Poll::Ready(item.map(|result| {
result.map(|idx| {
let data = self.slab.remove(idx);
debug_assert!(data.next.is_none());
debug_assert!(data.prev.is_none());
Expired {
key: Key::new(idx),
data: data.inner,
deadline: self.start + Duration::from_millis(data.when),
}
})
}))
fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
DelayQueue::poll_next(self.get_mut(), cx)
}
}
+19 -6
View File
@@ -1,6 +1,6 @@
use crate::clock;
use crate::Delay;
use futures_core::Stream;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};
@@ -52,12 +52,9 @@ impl Interval {
pub(crate) fn new_with_delay(delay: Delay, duration: Duration) -> Interval {
Interval { delay, duration }
}
}
impl Stream for Interval {
type Item = Instant;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
/// TODO: dox
pub fn poll_next(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<Instant>> {
// Wait for the delay to be done
ready!(Pin::new(&mut self.delay).poll(cx));
@@ -72,4 +69,20 @@ impl Stream for Interval {
// Return the current instant
Poll::Ready(Some(now))
}
/// TODO: dox
pub async fn next(&mut self) -> Option<Instant> {
use async_util::future::poll_fn;
poll_fn(|cx| self.poll_next(cx)).await
}
}
#[cfg(feature = "async-traits")]
impl futures_core::Stream for Interval {
type Item = Instant;
fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
Interval::poll_next(self.get_mut(), cx)
}
}
+2 -5
View File
@@ -2,6 +2,7 @@
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![cfg_attr(test, deny(warnings))]
#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))]
#![feature(async_await)]
//! Utilities for tracking time.
//!
@@ -41,9 +42,8 @@ macro_rules! ready {
}
pub mod clock;
#[cfg(feature = "delay-queue")]
pub mod delay_queue;
#[cfg(feature = "throttle")]
#[cfg(feature = "async-traits")]
pub mod throttle;
pub mod timeout;
pub mod timer;
@@ -51,16 +51,13 @@ pub mod timer;
mod atomic;
mod delay;
mod error;
#[cfg(feature = "interval")]
mod interval;
mod wheel;
pub use delay::Delay;
#[cfg(feature = "delay-queue")]
#[doc(inline)]
pub use delay_queue::DelayQueue;
pub use error::Error;
#[cfg(feature = "interval")]
pub use interval::Interval;
#[doc(inline)]
pub use timeout::Timeout;
+1 -1
View File
@@ -25,7 +25,7 @@ impl<T> Throttle<T> {
pub fn new(stream: T, duration: Duration) -> Self {
Self {
delay: Delay::new_timeout(clock::now() + duration, duration),
has_delayed: false,
has_delayed: true,
stream: stream,
}
}
+6 -6
View File
@@ -6,8 +6,6 @@
use crate::clock::now;
use crate::Delay;
#[cfg(feature = "timeout-stream")]
use futures_core::Stream;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
@@ -175,10 +173,10 @@ where
}
}
#[cfg(feature = "timeout-stream")]
impl<T> Stream for Timeout<T>
#[cfg(feature = "async-traits")]
impl<T> futures_core::Stream for Timeout<T>
where
T: Stream,
T: futures_core::Stream,
{
type Item = Result<T::Item, Elapsed>;
@@ -202,8 +200,10 @@ where
}
// Now check the timer
ready!(self.map_unchecked_mut(|me| &mut me.delay).poll(cx));
ready!(self.as_mut().map_unchecked_mut(|me| &mut me.delay).poll(cx));
// if delay was ready, timeout elapsed!
self.as_mut().get_unchecked_mut().delay.reset_timeout();
Poll::Ready(Some(Err(Elapsed(()))))
}
}
+3 -4
View File
@@ -4,7 +4,6 @@ use std::cell::RefCell;
use std::fmt;
use std::sync::{Arc, Weak};
use std::time::Instant;
use tokio_executor::Enter;
/// Handle to timer instance.
///
@@ -58,9 +57,9 @@ thread_local! {
///
/// [`Delay`]: ../struct.Delay.html
/// [`Delay::new`]: ../struct.Delay.html#method.new
pub fn with_default<F, R>(handle: &Handle, enter: &mut Enter, f: F) -> R
pub fn with_default<F, R>(handle: &Handle, f: F) -> R
where
F: FnOnce(&mut Enter) -> R,
F: FnOnce() -> R,
{
// Ensure that the timer is removed from the thread-local context
// when leaving the scope. This handles cases that involve panicking.
@@ -96,7 +95,7 @@ where
*current = Some(handle.clone());
}
f(enter)
f()
})
}
+1 -1
View File
@@ -43,7 +43,7 @@ impl Registration {
}
// Used by `Timeout<Stream>`
#[cfg(feature = "timeout-stream")]
#[cfg(feature = "async-traits")]
pub fn reset_timeout(&mut self) {
let deadline = crate::clock::now() + self.entry.time_ref().duration;
self.entry.time_mut().deadline = deadline;