timer: move tokio-timer into tokio crate (#1674)

A step towards collapsing Tokio sub crates into a single `tokio`
crate (#1318).

The `timer` implementation is now provided by the main `tokio` crate.
The `timer` functionality may still be excluded from the build by
skipping the `timer` feature flag.
This commit is contained in:
Carl Lerche
2019-10-21 16:45:13 -07:00
committed by GitHub
parent c9bcbe77b9
commit b8cee1a60a
53 changed files with 216 additions and 771 deletions
-1
View File
@@ -9,7 +9,6 @@ members = [
"tokio-net",
"tokio-sync",
"tokio-test",
"tokio-timer",
"tokio-tls",
"build-tests",
]
-2
View File
@@ -70,8 +70,6 @@ jobs:
tokio-sync:
- async-traits
tokio-macros: []
tokio-timer:
- async-traits
tokio-test: []
# Test compilation failure
-1
View File
@@ -8,5 +8,4 @@ tokio-io = { path = "tokio-io" }
tokio-macros = { path = "tokio-macros" }
tokio-net = { path = "tokio-net" }
tokio-sync = { path = "tokio-sync" }
tokio-timer = { path = "tokio-timer" }
tokio-tls = { path = "tokio-tls" }
-1
View File
@@ -24,7 +24,6 @@ tokio = { version = "=0.2.0-alpha.6", path = "../tokio" }
tokio-executor = { version = "=0.2.0-alpha.6", path = "../tokio-executor" }
tokio-io = { version = "=0.2.0-alpha.6", path = "../tokio-io" }
tokio-sync = { version = "=0.2.0-alpha.6", path = "../tokio-sync" }
tokio-timer = { version = "=0.3.0-alpha.6", path = "../tokio-timer" }
futures-core-preview = "=0.3.0-alpha.19"
pin-convert = "0.1.0"
+6 -6
View File
@@ -1,11 +1,11 @@
//! A mocked clock for use with `tokio_timer` based futures.
//! A mocked clock for use with `tokio::timer` based futures.
//!
//! # Example
//!
//! ```
//! use tokio::clock;
//! use tokio::timer::delay;
//! use tokio_test::{assert_ready, assert_pending, task};
//! use tokio_timer::delay;
//!
//! use std::time::Duration;
//!
@@ -22,9 +22,9 @@
//! });
//! ```
use tokio::timer::clock::{Clock, Now};
use tokio::timer::Timer;
use tokio_executor::park::{Park, Unpark};
use tokio_timer::clock::{Clock, Now};
use tokio_timer::Timer;
use std::marker::PhantomData;
use std::rc::Rc;
@@ -125,13 +125,13 @@ impl MockClock {
where
F: FnOnce(&mut Handle) -> R,
{
::tokio_timer::clock::with_default(&self.clock, || {
tokio::timer::clock::with_default(&self.clock, || {
let park = self.time.mock_park();
let timer = Timer::new(park);
let handle = timer.handle();
let time = self.time.clone();
let _timer = ::tokio_timer::set_default(&handle);
let _timer = tokio::timer::set_default(&handle);
let mut handle = Handle::new(timer, time);
f(&mut handle)
// lazy(|| Ok::<_, ()>(f(&mut handle))).wait().unwrap()
+5 -41
View File
@@ -16,6 +16,11 @@
//! [`AsyncRead`]: tokio_io::AsyncRead
//! [`AsyncWrite`]: tokio_io::AsyncWrite
use tokio::timer::{clock, timer, Delay};
use tokio_io::{AsyncRead, AsyncWrite, Buf};
use tokio_sync::mpsc;
use futures_core::ready;
use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin;
@@ -23,11 +28,6 @@ use std::task::{self, Poll, Waker};
use std::time::{Duration, Instant};
use std::{cmp, io};
use futures_core::ready;
use tokio_io::{AsyncRead, AsyncWrite, Buf};
use tokio_sync::mpsc;
use tokio_timer::{clock, timer, Delay};
/// An I/O object that follows a predefined script.
///
/// This value is created by `Builder` and implements `AsyncRead` + `AsyncWrite`. It
@@ -268,42 +268,6 @@ impl Inner {
}
}
/*
impl io::Read for Mock {
fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
if self.is_async() {
tokio::async_read(self, dst)
} else {
self.sync_read(dst)
}
}
}
impl io::Write for Mock {
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
if self.is_async() {
tokio::async_write(self, src)
} else {
self.sync_write(src)
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
*/
/*
use self::futures::{Future, Stream, Poll, Async};
use self::futures::sync::mpsc;
use self::futures::task::{self, Task};
use self::tokio_io::{AsyncRead, AsyncWrite};
use self::tokio_timer::{Timer, Sleep};
use std::io;
*/
// ===== impl Inner =====
impl Mock {
+3 -2
View File
@@ -1,8 +1,9 @@
#![warn(rust_2018_idioms)]
use std::time::{Duration, Instant};
use tokio::timer::delay;
use tokio_test::block_on;
use tokio_timer::delay;
use std::time::{Duration, Instant};
#[test]
fn async_block() {
+8 -26
View File
@@ -1,12 +1,11 @@
#![cfg(feature = "broken")]
#![warn(rust_2018_idioms)]
use futures::Future;
use std::time::{Duration, Instant};
use tokio::timer::delay;
use tokio_test::clock::MockClock;
use tokio_test::task::MockTask;
use tokio_test::{assert_not_ready, assert_ready};
use tokio_timer::delay;
use tokio_test::task;
use tokio_test::{assert_pending, assert_ready};
use std::time::{Duration, Instant};
#[test]
fn clock() {
@@ -14,30 +13,13 @@ fn clock() {
mock.enter(|handle| {
let deadline = Instant::now() + Duration::from_secs(1);
let mut delay = delay(deadline);
let mut delay = task::spawn(delay(deadline));
assert_not_ready!(delay.poll());
assert_pending!(delay.poll());
handle.advance(Duration::from_secs(2));
assert_ready!(delay.poll());
});
}
#[test]
fn notify() {
let deadline = Instant::now() + Duration::from_secs(1);
let mut mock = MockClock::new();
let mut task = MockTask::new();
mock.enter(|handle| {
let mut delay = delay(deadline);
task.enter(|| assert_not_ready!(delay.poll()));
handle.advance(Duration::from_secs(1));
assert!(task.is_notified());
assert!(delay.is_woken());
assert_ready!(delay.poll());
});
}
-102
View File
@@ -1,102 +0,0 @@
# 0.3.0-alpha.6 (September 30, 2019)
- Move to `futures-*-preview 0.3.0-alpha.19`
- Move to `pin-project 0.4`
# 0.3.0-alpha.5 (September 19, 2019)
### Changed
- rename `sleep` to `delay_for` (#1518).
# 0.3.0-alpha.4 (August 29, 2019)
- Track tokio release.
# 0.3.0-alpha.3 (August 28, 2019)
### Changed
- `delay(...)` instead of `Delay::new(...)` (#1440).
# 0.3.0-alpha.2 (August 17, 2019)
### Changed
- Update `futures` dependency to 0.3.0-alpha.18.
- Switch `with_default(..., || )` to `set_default(...) -> Guard` (#1449).
# 0.3.0-alpha.1 (August 8, 2019)
### Changed
- Switch to `async`, `await`, and `std::future`.
# 0.2.11 (May 14, 2019)
### Added
- `Handle::timeout` API, replacing the deprecated `Handle::deadline` (#1074).
# 0.2.10 (February 4, 2019)
### Fixed
- `DelayQueue` when multiple delays are reset (#871).
# 0.2.9 (January 24, 2019)
### Fixed
- `DelayQueue` timing logic when inserting / resetting a delay (#851, #863).
- Documentation links (#842, #844, #845)
# 0.2.8 (November 21, 2018)
* Implement throttle combinator (#736).
* Derive `Clone` for `delay_queue::Key` (#730).
* Bump internal dependencies (#753).
# 0.2.7 (September 27, 2018)
* Fix `Timeout` on error bug (#648).
* Miscellaneous documentation improvements.
# 0.2.6 (August 23, 2018)
* Implement `Default` for `timer::Handle` (#553)
* Provide `DelayQueue` utility (#550)
* Reduce size of `Delay` struct (#554)
* Introduce `Timeout`, deprecate `Deadline` (#558)
# 0.2.5 (August 6, 2018)
* Add `Interval::interval` shortcut (#492).
# 0.2.4 (June 6, 2018)
* Add `sleep` function for easy interval delays (#347).
* Provide `clock::now()`, a configurable source of time (#381).
# 0.2.3 (May 2, 2018)
* Improve parking semantics (#327).
# 0.2.2 (Skipped due to failure in counting module)
# 0.2.1 (April 2, 2018)
* Fix build on 32-bit systems (#274).
# 0.2.0 (March 30, 2018)
* Rewrite from scratch using a hierarchical wheel strategy (#249).
# 0.1.2 (Jun 27, 2017)
* Allow naming timer thread.
* Track changes in dependencies.
# 0.1.1 (Apr 6, 2017)
* Set Rust v1.14 as the minimum supported version.
* Fix bug related to intervals.
* Impl `PartialEq + Eq` for TimerError.
* Add `Debug` implementations.
# 0.1.0 (Jan 11, 2017)
* Initial Release
-46
View File
@@ -1,46 +0,0 @@
[package]
name = "tokio-timer"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.3.x" git tag.
version = "0.3.0-alpha.6"
edition = "2018"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
readme = "README.md"
documentation = "https://docs.rs/tokio-timer/0.3.0-alpha.6/tokio_timer"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://github.com/tokio-rs/tokio"
description = """
Timer facilities for Tokio
"""
[features]
async-traits = []
[dependencies]
tokio-executor = { version = "=0.2.0-alpha.6", path = "../tokio-executor" }
tokio-sync = { version = "=0.2.0-alpha.6", path = "../tokio-sync" }
futures-core-preview = "=0.3.0-alpha.19"
futures-util-preview = "=0.3.0-alpha.19"
crossbeam-utils = "0.6.0"
# Backs `DelayQueue`
slab = "0.4.1"
# optionals
[dev-dependencies]
tokio = { version = "=0.2.0-alpha.6", path = "../tokio" }
tokio-sync = { version = "=0.2.0-alpha.6", path = "../tokio-sync", features = ["async-traits"] }
tokio-test = { version = "=0.2.0-alpha.6", path = "../tokio-test" }
rand = "0.7"
[package.metadata.docs.rs]
all-features = true
-25
View File
@@ -1,25 +0,0 @@
Copyright (c) 2019 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-13
View File
@@ -1,13 +0,0 @@
# tokio-timer
Timer facilities for Tokio
## License
This project is licensed under the [MIT license](LICENSE).
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Tokio by you, shall be licensed as MIT, without any additional
terms or conditions.
-105
View File
@@ -1,105 +0,0 @@
#![doc(html_root_url = "https://docs.rs/tokio-timer/0.3.0-alpha.6")]
#![warn(
missing_debug_implementations,
missing_docs,
rust_2018_idioms,
unreachable_pub
)]
#![deny(intra_doc_link_resolution_failure)]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
//! Utilities for tracking time.
//!
//! This crate provides a number of utilities for working with periods of time:
//!
//! * [`Delay`]: A future that completes at a specified instant in time.
//!
//! * [`Interval`] A stream that yields at fixed time intervals.
//!
//! * [`Throttle`]: Throttle down a stream by enforcing a fixed delay between items.
//!
//! * [`Timeout`]: Wraps a future or stream, setting an upper bound to the
//! amount of time it is allowed to execute. If the future or stream does not
//! complete in time, then it is canceled and an error is returned.
//!
//! * [`DelayQueue`]: A queue where items are returned once the requested delay
//! has expired.
//!
//! These three types are backed by a [`Timer`] instance. In order for
//! [`Delay`], [`Interval`], and [`Timeout`] to function, the associated
//! [`Timer`] instance must be running on some thread.
//!
//! [`Delay`]: struct.Delay.html
//! [`DelayQueue`]: struct.DelayQueue.html
//! [`Throttle`]: throttle::Throttle
//! [`Timeout`]: struct.Timeout.html
//! [`Interval`]: struct.Interval.html
//! [`Timer`]: timer::Timer
pub mod clock;
pub mod delay_queue;
#[cfg(feature = "async-traits")]
pub mod throttle;
pub mod timeout;
pub mod timer;
mod atomic;
mod delay;
mod error;
mod interval;
mod wheel;
pub use delay::Delay;
#[doc(inline)]
pub use delay_queue::DelayQueue;
pub use error::Error;
pub use interval::Interval;
#[doc(inline)]
pub use timeout::Timeout;
pub use timer::{set_default, Timer};
use std::time::{Duration, Instant};
/// Create a Future that completes at `deadline`.
pub fn delay(deadline: Instant) -> Delay {
Delay::new(deadline)
}
/// Create a Future that completes in `duration` from now.
///
/// Equivalent to `delay(tokio_timer::clock::now() + duration)`. Analogous to `std::thread::sleep`.
pub fn delay_for(duration: Duration) -> Delay {
delay(clock::now() + duration)
}
// ===== Internal utils =====
enum Round {
Up,
Down,
}
/// Convert a `Duration` to milliseconds, rounding up and saturating at
/// `u64::MAX`.
///
/// The saturating is fine because `u64::MAX` milliseconds are still many
/// million years.
#[inline]
fn ms(duration: Duration, round: Round) -> u64 {
const NANOS_PER_MILLI: u32 = 1_000_000;
const MILLIS_PER_SEC: u64 = 1_000;
// Round up.
let millis = match round {
Round::Up => (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI,
Round::Down => duration.subsec_millis(),
};
duration
.as_secs()
.saturating_mul(MILLIS_PER_SEC)
.saturating_add(u64::from(millis))
}
-265
View File
@@ -1,265 +0,0 @@
#![allow(unused_macros, unused_imports, dead_code, deprecated)]
use tokio_executor::park::{Park, Unpark};
use tokio_timer::clock::Now;
use tokio_timer::timer::Timer;
use futures::future::{lazy, Future};
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
#[macro_export]
macro_rules! assert_ready {
($f:expr) => {{
use ::futures::Async::*;
match $f.poll().unwrap() {
Ready(v) => v,
NotReady => panic!("NotReady"),
}
}};
($f:expr, $($msg:expr),+) => {{
use ::futures::Async::*;
match $f.poll().unwrap() {
Ready(v) => v,
NotReady => {
let msg = format!($($msg),+);
panic!("NotReady; {}", msg)
}
}
}}
}
#[macro_export]
macro_rules! assert_ready_eq {
($f:expr, $expect:expr) => {
assert_eq!($f.poll().unwrap(), ::futures::Async::Ready($expect));
};
}
#[macro_export]
macro_rules! assert_not_ready {
($f:expr) => {{
let res = $f.poll().unwrap();
assert!(!res.is_ready(), "actual={:?}", res)
}};
($f:expr, $($msg:expr),+) => {{
let res = $f.poll().unwrap();
if res.is_ready() {
let msg = format!($($msg),+);
panic!("actual={:?}; {}", res, msg);
}
}};
}
#[macro_export]
macro_rules! assert_elapsed {
($f:expr) => {
assert!($f.poll().unwrap_err().is_elapsed());
};
}
#[derive(Debug)]
pub struct MockTime {
inner: Inner,
_p: PhantomData<Rc<()>>,
}
#[derive(Debug)]
pub struct MockNow {
inner: Inner,
}
#[derive(Debug)]
pub struct MockPark {
inner: Inner,
_p: PhantomData<Rc<()>>,
}
#[derive(Debug)]
pub struct MockUnpark {
inner: Inner,
}
type Inner = Arc<Mutex<State>>;
#[derive(Debug)]
struct State {
base: Instant,
advance: Duration,
unparked: bool,
park_for: Option<Duration>,
}
pub fn ms(num: u64) -> Duration {
Duration::from_millis(num)
}
pub trait IntoTimeout {
fn into_timeout(self) -> Option<Duration>;
}
impl IntoTimeout for Option<Duration> {
fn into_timeout(self) -> Self {
self
}
}
impl IntoTimeout for Duration {
fn into_timeout(self) -> Option<Duration> {
Some(self)
}
}
/// Turn the timer state once
pub fn turn<T: IntoTimeout>(timer: &mut Timer<MockPark>, duration: T) {
timer.turn(duration.into_timeout()).unwrap();
}
/// Advance the timer the specified amount
pub fn advance(timer: &mut Timer<MockPark>, duration: Duration) {
let inner = timer.get_park().inner.clone();
let deadline = inner.lock().unwrap().now() + duration;
while inner.lock().unwrap().now() < deadline {
let dur = deadline - inner.lock().unwrap().now();
turn(timer, dur);
}
}
pub fn mocked<F, R>(f: F) -> R
where
F: FnOnce(&mut Timer<MockPark>, &mut MockTime) -> R,
{
mocked_with_now(Instant::now(), f)
}
pub fn mocked_with_now<F, R>(now: Instant, f: F) -> R
where
F: FnOnce(&mut Timer<MockPark>, &mut MockTime) -> R,
{
let mut time = MockTime::new(now);
let park = time.mock_park();
let now = ::tokio_timer::clock::Clock::new_with_now(time.mock_now());
let mut enter = ::tokio_executor::enter().unwrap();
::tokio_timer::clock::with_default(&now, &mut enter, |enter| {
let mut timer = Timer::new(park);
let handle = timer.handle();
::tokio_timer::with_default(&handle, enter, |_| {
lazy(|| Ok::<_, ()>(f(&mut timer, &mut time)))
.wait()
.unwrap()
})
})
}
impl MockTime {
pub fn new(now: Instant) -> MockTime {
let state = State {
base: now,
advance: Duration::default(),
unparked: false,
park_for: None,
};
MockTime {
inner: Arc::new(Mutex::new(state)),
_p: PhantomData,
}
}
pub fn mock_now(&self) -> MockNow {
let inner = self.inner.clone();
MockNow { inner }
}
pub fn mock_park(&self) -> MockPark {
let inner = self.inner.clone();
MockPark {
inner,
_p: PhantomData,
}
}
pub fn now(&self) -> Instant {
self.inner.lock().unwrap().now()
}
/// Returns the total amount of time the time has been advanced.
pub fn advanced(&self) -> Duration {
self.inner.lock().unwrap().advance
}
pub fn advance(&self, duration: Duration) {
let mut inner = self.inner.lock().unwrap();
inner.advance(duration);
}
/// The next call to park_timeout will be for this duration, regardless of
/// the timeout passed to `park_timeout`.
pub fn park_for(&self, duration: Duration) {
self.inner.lock().unwrap().park_for = Some(duration);
}
}
impl Park for MockPark {
type Unpark = MockUnpark;
type Error = ();
fn unpark(&self) -> Self::Unpark {
let inner = self.inner.clone();
MockUnpark { inner }
}
fn park(&mut self) -> Result<(), Self::Error> {
let mut inner = self.inner.lock().map_err(|_| ())?;
let duration = inner.park_for.take().expect("call park_for first");
inner.advance(duration);
Ok(())
}
fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
let mut inner = self.inner.lock().unwrap();
if let Some(duration) = inner.park_for.take() {
inner.advance(duration);
} else {
inner.advance(duration);
}
Ok(())
}
}
impl Unpark for MockUnpark {
fn unpark(&self) {
if let Ok(mut inner) = self.inner.lock() {
inner.unparked = true;
}
}
}
impl Now for MockNow {
fn now(&self) -> Instant {
self.inner.lock().unwrap().now()
}
}
impl State {
fn now(&self) -> Instant {
self.base + self.advance
}
fn advance(&mut self, duration: Duration) {
self.advance += duration;
}
}
+5 -2
View File
@@ -59,7 +59,7 @@ rt-full = [
signal = ["tokio-net/signal"]
sync = ["tokio-sync"]
tcp = ["io", "tokio-net/tcp"]
timer = ["tokio-timer"]
timer = ["crossbeam-utils", "slab"]
tracing = ["tracing-core"]
udp = ["io", "tokio-net/udp"]
uds = ["io", "tokio-net/uds"]
@@ -72,14 +72,16 @@ futures-util-preview = { version = "=0.3.0-alpha.19", features = ["sink"] }
# Everything else is optional...
bytes = { version = "0.4", optional = true }
crossbeam-utils = { version = "0.6.0", optional = true }
num_cpus = { version = "1.8.0", optional = true }
# Backs `DelayQueue`
slab = { version = "0.4.1", optional = true }
tokio-codec = { version = "=0.2.0-alpha.6", optional = true, path = "../tokio-codec" }
tokio-io = { version = "=0.2.0-alpha.6", optional = true, features = ["util"], path = "../tokio-io" }
tokio-executor = { version = "=0.2.0-alpha.6", optional = true, path = "../tokio-executor" }
tokio-macros = { version = "=0.2.0-alpha.6", optional = true, path = "../tokio-macros" }
tokio-net = { version = "=0.2.0-alpha.6", optional = true, features = ["async-traits"], path = "../tokio-net" }
tokio-sync = { version = "=0.2.0-alpha.6", optional = true, path = "../tokio-sync", features = ["async-traits"] }
tokio-timer = { version = "=0.3.0-alpha.6", optional = true, path = "../tokio-timer", features = ["async-traits"] }
tracing-core = { version = "0.1", optional = true }
[target.'cfg(feature = "tracing")'.dependencies]
@@ -98,6 +100,7 @@ http = "0.1"
httparse = "1.0"
libc = "0.2"
num_cpus = "1.0"
rand = "0.7.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tempfile = "3.1.0"
+3 -4
View File
@@ -2,14 +2,13 @@
//!
//! This module provides the [`now`][n] function, which returns an `Instant`
//! representing "now". The source of time used by this function is configurable
//! (via the [`tokio-timer`] crate) and allows mocking out the source of time in
//! tests or performing caching operations to reduce the number of syscalls.
//! and allows mocking out the source of time in tests or performing caching
//! operations to reduce the number of syscalls.
//!
//! Note that, because the source of time is configurable, it is possible to
//! observe non-monotonic behavior when calling [`now`][n] from different
//! executors.
//!
//! [n]: fn.now.html
//! [`tokio-timer`]: https://docs.rs/tokio-timer/0.2/tokio_timer/clock/index.html
pub use tokio_timer::clock::now;
pub use crate::timer::clock::now;
+1 -1
View File
@@ -1,7 +1,7 @@
//! Asynchronous values.
#[cfg(feature = "timer")]
use tokio_timer::Timeout;
use crate::timer::Timeout;
#[cfg(feature = "timer")]
use std::time::Duration;
+4 -4
View File
@@ -1,9 +1,9 @@
use crate::runtime::current_thread::Runtime;
use crate::timer::clock::Clock;
use crate::timer::timer::Timer;
use tokio_executor::current_thread::CurrentThread;
use tokio_net::driver::Reactor;
use tokio_timer::clock::Clock;
use tokio_timer::timer::Timer;
use std::io;
@@ -24,7 +24,7 @@ use std::io;
///
/// ```
/// use tokio::runtime::current_thread::Builder;
/// use tokio_timer::clock::Clock;
/// use tokio::timer::clock::Clock;
///
/// # pub fn main() {
/// // build Runtime
@@ -66,7 +66,7 @@ impl Builder {
// Place a timer wheel on top of the reactor. If there are no timeouts to fire, it'll let the
// reactor pick up some new external events.
let timer = Timer::new_with_now(reactor, self.clock.clone());
let timer = Timer::new_with_clock(reactor, self.clock.clone());
let timer_handle = timer.handle();
// And now put a single-threaded executor on top of the timer. When there are no futures ready
+2 -2
View File
@@ -1,10 +1,10 @@
use crate::runtime::current_thread::Builder;
use crate::timer::clock::{self, Clock};
use crate::timer::timer::{self, Timer};
use tokio_executor::current_thread::Handle as ExecutorHandle;
use tokio_executor::current_thread::{self, CurrentThread};
use tokio_net::driver::{self, Reactor};
use tokio_timer::clock::{self, Clock};
use tokio_timer::timer::{self, Timer};
use std::error::Error;
use std::fmt;
+1 -2
View File
@@ -20,7 +20,7 @@
//!
//! * Spawn a background thread running a [`Reactor`] instance.
//! * Start a [`ThreadPool`] for executing futures.
//! * Run an instance of [`Timer`] **per** thread pool worker thread.
//! * Run an instance of `Timer` **per** thread pool worker thread.
//!
//! The thread pool uses a work-stealing strategy and is configured to start a
//! worker thread for each CPU core available on the system. This tends to be
@@ -127,7 +127,6 @@
//! [`ThreadPool`]: https://docs.rs/tokio-executor/0.2.0-alpha.2/tokio_executor/threadpool/struct.ThreadPool.html
//! [`run`]: fn.run.html
//! [`tokio::spawn`]: ../executor/fn.spawn.html
//! [`Timer`]: https://docs.rs/tokio-timer/0.2/tokio_timer/timer/struct.Timer.html
//! [`tokio::main`]: ../../tokio_macros/attr.main.html
pub mod current_thread;
+4 -4
View File
@@ -1,9 +1,9 @@
use super::{Inner, Runtime};
use crate::timer::clock::{self, Clock};
use crate::timer::timer::{self, Timer};
use tokio_executor::thread_pool;
use tokio_net::driver::{self, Reactor};
use tokio_timer::clock::{self, Clock};
use tokio_timer::timer::{self, Timer};
use tracing_core as trace;
use std::{fmt, io};
@@ -26,7 +26,7 @@ use std::sync::{Arc, Mutex};
///
/// ```
/// use tokio::runtime::Builder;
/// use tokio_timer::clock::Clock;
/// use tokio::timer::clock::Clock;
///
/// fn main() {
/// // build Runtime
@@ -233,7 +233,7 @@ impl Builder {
reactor_handles.push(reactor.handle());
// Create a new timer.
let timer = Timer::new_with_now(reactor, self.clock.clone());
let timer = Timer::new_with_clock(reactor, self.clock.clone());
timer_handles.push(timer.handle());
timers.push(Mutex::new(Some(timer)));
}
+2 -1
View File
@@ -9,9 +9,10 @@ pub use self::spawner::Spawner;
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
pub use tokio_executor::thread_pool::JoinHandle;
use crate::timer::timer;
use tokio_executor::thread_pool::ThreadPool;
use tokio_net::driver;
use tokio_timer::timer;
use tracing_core as trace;
use std::future::Future;
+1 -1
View File
@@ -4,7 +4,7 @@
use std::time::Duration;
#[cfg(feature = "timer")]
use tokio_timer::{throttle::Throttle, Timeout};
use crate::timer::{throttle::Throttle, Timeout};
#[doc(inline)]
pub use futures_core::Stream;
@@ -20,7 +20,6 @@ mod now;
pub use self::now::Now;
use crate::timer;
use std::cell::Cell;
use std::fmt;
use std::sync::Arc;
@@ -57,7 +56,7 @@ thread_local! {
/// # Examples
///
/// ```
/// # use tokio_timer::clock;
/// # use tokio::timer::clock;
/// let now = clock::now();
/// ```
pub fn now() -> Instant {
@@ -102,13 +101,6 @@ impl Clock {
}
}
#[allow(deprecated)]
impl timer::Now for Clock {
fn now(&mut self) -> Instant {
Clock::now(self)
}
}
impl fmt::Debug for Clock {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Clock")
@@ -1,4 +1,5 @@
use crate::timer::{HandlePriv, Registration};
use crate::timer::timer::{HandlePriv, Registration};
use futures_core::ready;
use std::future::Future;
use std::pin::Pin;
@@ -78,8 +79,6 @@ impl Delay {
self.registration.reset(deadline);
}
// Used by `Timeout<Stream>`
#[cfg(feature = "async-traits")]
pub(crate) fn reset_timeout(&mut self) {
self.registration.reset_timeout();
}
@@ -4,10 +4,10 @@
//!
//! [`DelayQueue`]: struct.DelayQueue.html
use crate::clock::now;
use crate::timer::Handle;
use crate::wheel::{self, Wheel};
use crate::{Delay, Error};
use crate::timer::clock::now;
use crate::timer::timer::Handle;
use crate::timer::wheel::{self, Wheel};
use crate::timer::{Delay, Error};
use futures_core::ready;
use slab::Slab;
@@ -217,7 +217,7 @@ impl<T> DelayQueue<T> {
/// # Examples
///
/// ```rust
/// # use tokio_timer::DelayQueue;
/// # use tokio::timer::DelayQueue;
/// let delay_queue: DelayQueue<u32> = DelayQueue::new();
/// ```
pub fn new() -> DelayQueue<T> {
@@ -231,8 +231,8 @@ impl<T> DelayQueue<T> {
/// # Examples
///
/// ```rust,no_run
/// # use tokio_timer::DelayQueue;
/// use tokio_timer::timer::Handle;
/// # use tokio::timer::DelayQueue;
/// use tokio::timer::timer::Handle;
///
/// let handle = Handle::default();
/// let delay_queue: DelayQueue<u32> = DelayQueue::with_capacity_and_handle(0, &handle);
@@ -258,7 +258,7 @@ impl<T> DelayQueue<T> {
/// # Examples
///
/// ```rust
/// # use tokio_timer::DelayQueue;
/// # use tokio::timer::DelayQueue;
/// # use std::time::Duration;
/// let mut delay_queue = DelayQueue::with_capacity(10);
///
@@ -464,7 +464,7 @@ impl<T> DelayQueue<T> {
/// assert_eq!(*item.get_ref(), "foo");
/// ```
pub fn remove(&mut self, key: &Key) -> Expired<T> {
use crate::wheel::Stack;
use crate::timer::wheel::Stack;
// Special case the `expired` queue
if self.slab[key.index].expired {
@@ -607,7 +607,7 @@ impl<T> DelayQueue<T> {
/// # Examples
///
/// ```rust
/// use tokio_timer::DelayQueue;
/// use tokio::timer::DelayQueue;
///
/// let delay_queue: DelayQueue<i32> = DelayQueue::with_capacity(10);
/// assert_eq!(delay_queue.capacity(), 10);
@@ -636,7 +636,7 @@ impl<T> DelayQueue<T> {
/// # Examples
///
/// ```
/// use tokio_timer::DelayQueue;
/// use tokio::timer::DelayQueue;
/// use std::time::Duration;
///
/// let mut delay_queue = DelayQueue::new();
@@ -658,7 +658,7 @@ impl<T> DelayQueue<T> {
/// # Examples
///
/// ```
/// use tokio_timer::DelayQueue;
/// use tokio::timer::DelayQueue;
/// use std::time::Duration;
///
/// let mut delay_queue = DelayQueue::new();
@@ -690,7 +690,8 @@ impl<T> DelayQueue<T> {
ready!(Pin::new(&mut *delay).poll(cx));
}
let now = crate::ms(delay.deadline() - self.start, crate::Round::Down);
let now =
crate::timer::ms(delay.deadline() - self.start, crate::timer::Round::Down);
self.poll = wheel::Poll::new(now);
}
@@ -713,7 +714,7 @@ impl<T> DelayQueue<T> {
let when = if when < self.start {
0
} else {
crate::ms(when - self.start, crate::Round::Up)
crate::timer::ms(when - self.start, crate::timer::Round::Up)
};
cmp::max(when, self.wheel.elapsed())
@@ -723,7 +724,6 @@ impl<T> DelayQueue<T> {
// We never put `T` in a `Pin`...
impl<T> Unpin 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.
@@ -1,5 +1,4 @@
use crate::clock;
use crate::Delay;
use crate::timer::{clock, Delay};
use futures_core::ready;
use futures_util::future::poll_fn;
@@ -40,7 +39,7 @@ impl Interval {
/// Creates new `Interval` that yields with interval of `duration`.
///
/// The function is shortcut for `Interval::new(tokio_timer::clock::now() + duration, duration)`.
/// The function is shortcut for `Interval::new(tokio::timer::clock::now() + duration, duration)`.
///
/// The `duration` argument must be a non-zero duration.
///
@@ -98,14 +97,12 @@ impl Interval {
}
}
#[cfg(feature = "async-traits")]
impl futures_core::FusedStream for Interval {
fn is_terminated(&self) -> bool {
false
}
}
#[cfg(feature = "async-traits")]
impl futures_core::Stream for Interval {
type Item = Instant;
+72 -3
View File
@@ -74,6 +74,75 @@
//! [Interval]: struct.Interval.html
//! [`DelayQueue`]: struct.DelayQueue.html
pub use tokio_timer::{
delay, delay_for, delay_queue, timeout, Delay, DelayQueue, Error, Interval, Timeout,
};
pub mod clock;
pub mod delay_queue;
#[doc(inline)]
pub use self::delay_queue::DelayQueue;
pub mod throttle;
// TODO: clean this up
#[allow(clippy::module_inception)]
pub mod timer;
pub use timer::{set_default, Timer};
pub mod timeout;
#[doc(inline)]
pub use timeout::Timeout;
mod atomic;
mod delay;
pub use self::delay::Delay;
mod error;
pub use error::Error;
mod interval;
pub use interval::Interval;
mod wheel;
use std::time::{Duration, Instant};
/// Create a Future that completes at `deadline`.
pub fn delay(deadline: Instant) -> Delay {
Delay::new(deadline)
}
/// Create a Future that completes in `duration` from now.
///
/// Equivalent to `delay(tokio::timer::clock::now() + duration)`. Analogous to `std::thread::sleep`.
pub fn delay_for(duration: Duration) -> Delay {
delay(clock::now() + duration)
}
// ===== Internal utils =====
enum Round {
Up,
Down,
}
/// Convert a `Duration` to milliseconds, rounding up and saturating at
/// `u64::MAX`.
///
/// The saturating is fine because `u64::MAX` milliseconds are still many
/// million years.
#[inline]
fn ms(duration: Duration, round: Round) -> u64 {
const NANOS_PER_MILLI: u32 = 1_000_000;
const MILLIS_PER_SEC: u64 = 1_000;
// Round up.
let millis = match round {
Round::Up => (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI,
Round::Down => duration.subsec_millis(),
};
duration
.as_secs()
.saturating_mul(MILLIS_PER_SEC)
.saturating_add(u64::from(millis))
}
@@ -1,6 +1,7 @@
//! Slow down a stream by enforcing a delay between items.
use crate::{clock, Delay};
use crate::timer::{clock, Delay};
use futures_core::ready;
use futures_core::Stream;
use std::{
@@ -4,9 +4,9 @@
//!
//! [`Timeout`]: struct.Timeout.html
use crate::clock::now;
use crate::Delay;
#[cfg(feature = "async-traits")]
use crate::timer::clock::now;
use crate::timer::Delay;
use futures_core::ready;
use std::fmt;
use std::future::Future;
@@ -180,7 +180,6 @@ where
}
}
#[cfg(feature = "async-traits")]
impl<T> futures_core::Stream for Timeout<T>
where
T: futures_core::Stream,
@@ -1,5 +1,6 @@
use super::Entry;
use crate::Error;
use crate::timer::Error;
use std::ptr;
use std::sync::atomic::AtomicPtr;
use std::sync::atomic::Ordering::SeqCst;
@@ -1,6 +1,9 @@
use crate::atomic::AtomicU64;
use crate::timer::{HandlePriv, Inner};
use crate::Error;
use crate::timer::atomic::AtomicU64;
use crate::timer::timer::{HandlePriv, Inner};
use crate::timer::Error;
use tokio_sync::AtomicWaker;
use crossbeam_utils::CachePadded;
use std::cell::UnsafeCell;
use std::ptr;
@@ -10,7 +13,6 @@ use std::sync::{Arc, Weak};
use std::task::{self, Poll};
use std::time::{Duration, Instant};
use std::u64;
use tokio_sync::AtomicWaker;
/// Internal state shared between a `Delay` instance and the timer.
///
@@ -1,6 +1,7 @@
use crate::clock::now;
use crate::timer::Inner;
use crate::{Delay, Error, /*Interval,*/ Timeout};
use crate::timer::clock::now;
use crate::timer::timer::Inner;
use crate::timer::{Delay, Error, Timeout};
use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
@@ -10,10 +10,6 @@
//! `Clone`, `Send`, and `Sync`. This type is used to create instances of
//! [`Delay`].
//!
//! The [`Now`] trait describes how to get an [`Instant`] representing the
//! current moment in time. [`SystemNow`] is the default implementation, where
//! [`Now::now`] is implemented by calling [`Instant::now`].
//!
//! [`Timer`] is generic over [`Now`]. This allows the source of time to be
//! customized. This ability is especially useful in tests and any environment
//! where determinism is necessary.
@@ -26,39 +22,38 @@
//! [`Delay`]: Delay
//! [`Now`]: clock::Now
//! [`Now::now`]: clock::Now::now
//! [`SystemNow`]: struct.SystemNow.html
//! [`Instant`]: std::time::Instant
//! [`Instant::now`]: std::time::Instant::now
// This allows the usage of the old `Now` trait.
#![allow(deprecated)]
mod atomic_stack;
mod entry;
mod handle;
mod now;
mod registration;
mod stack;
use self::atomic_stack::AtomicStack;
use self::entry::Entry;
use self::stack::Stack;
mod entry;
use self::entry::Entry;
mod handle;
pub(crate) use self::handle::HandlePriv;
pub use self::handle::{set_default, Handle};
pub use self::now::{Now, SystemNow};
mod registration;
pub(crate) use self::registration::Registration;
use crate::atomic::AtomicU64;
use crate::wheel;
use crate::Error;
mod stack;
use self::stack::Stack;
use crate::timer::atomic::AtomicU64;
use crate::timer::clock::Clock;
use crate::timer::wheel;
use crate::timer::Error;
use tokio_executor::park::{Park, ParkThread, Unpark};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::usize;
use std::{cmp, fmt};
use tokio_executor::park::{Park, ParkThread, Unpark};
/// Timer implementation that drives [`Delay`], [`Interval`], and [`Timeout`].
///
@@ -124,7 +119,7 @@ use tokio_executor::park::{Park, ParkThread, Unpark};
/// [`turn`]: #method.turn
/// [Handle.struct]: struct.Handle.html
#[derive(Debug)]
pub struct Timer<T, N = SystemNow> {
pub struct Timer<T> {
/// Shared state
inner: Arc<Inner>,
@@ -135,7 +130,7 @@ pub struct Timer<T, N = SystemNow> {
park: T,
/// Source of "now" instances
now: N,
clock: Clock,
}
/// Return value from the `turn` method on `Timer`.
@@ -183,11 +178,11 @@ where
///
/// [`handle`]: #method.handle
pub fn new(park: T) -> Self {
Timer::new_with_now(park, SystemNow::new())
Timer::new_with_clock(park, Clock::new())
}
}
impl<T, N> Timer<T, N> {
impl<T> Timer<T> {
/// Returns a reference to the underlying `Park` instance.
pub fn get_park(&self) -> &T {
&self.park
@@ -199,23 +194,22 @@ impl<T, N> Timer<T, N> {
}
}
impl<T, N> Timer<T, N>
impl<T> Timer<T>
where
T: Park,
N: Now,
{
/// Create a new `Timer` instance that uses `park` to block the current
/// thread and `now` to get the current `Instant`.
///
/// Specifying the source of time is useful when testing.
pub fn new_with_now(park: T, mut now: N) -> Self {
pub fn new_with_clock(park: T, clock: Clock) -> Self {
let unpark = Box::new(park.unpark());
Timer {
inner: Arc::new(Inner::new(now.now(), unpark)),
inner: Arc::new(Inner::new(clock.now(), unpark)),
wheel: wheel::Wheel::new(),
park,
now,
clock,
}
}
@@ -264,7 +258,10 @@ where
/// Run timer related logic
fn process(&mut self) {
let now = crate::ms(self.now.now() - self.inner.start, crate::Round::Down);
let now = crate::timer::ms(
self.clock.now() - self.inner.start,
crate::timer::Round::Down,
);
let mut poll = wheel::Poll::new(now);
while let Some(entry) = self.wheel.poll(&mut poll, &mut ()) {
@@ -315,7 +312,7 @@ where
///
/// Returns `None` if the entry was fired.
fn add_entry(&mut self, entry: Arc<Entry>, when: u64) {
use crate::wheel::InsertError;
use crate::timer::wheel::InsertError;
entry.set_when_internal(Some(when));
@@ -337,16 +334,15 @@ where
}
}
impl Default for Timer<ParkThread, SystemNow> {
impl Default for Timer<ParkThread> {
fn default() -> Self {
Timer::new(ParkThread::new())
}
}
impl<T, N> Park for Timer<T, N>
impl<T> Park for Timer<T>
where
T: Park,
N: Now,
{
type Unpark = T::Unpark;
type Error = T::Error;
@@ -360,7 +356,7 @@ where
match self.wheel.poll_at() {
Some(when) => {
let now = self.now.now();
let now = self.clock.now();
let deadline = self.expiration_instant(when);
if deadline > now {
@@ -384,7 +380,7 @@ where
match self.wheel.poll_at() {
Some(when) => {
let now = self.now.now();
let now = self.clock.now();
let deadline = self.expiration_instant(when);
if deadline > now {
@@ -404,7 +400,7 @@ where
}
}
impl<T, N> Drop for Timer<T, N> {
impl<T> Drop for Timer<T> {
fn drop(&mut self) {
use std::u64;
@@ -477,7 +473,7 @@ impl Inner {
return 0;
}
crate::ms(deadline - self.start, crate::Round::Up)
crate::timer::ms(deadline - self.start, crate::timer::Round::Up)
}
}
@@ -1,5 +1,6 @@
use crate::timer::{Entry, HandlePriv};
use crate::Error;
use crate::timer::timer::{Entry, HandlePriv};
use crate::timer::Error;
use std::sync::Arc;
use std::task::{self, Poll};
use std::time::{Duration, Instant};
@@ -45,7 +46,6 @@ impl Registration {
}
// Used by `Timeout<Stream>`
#[cfg(feature = "async-traits")]
pub(crate) fn reset_timeout(&mut self) {
let deadline = crate::clock::now() + self.entry.time_ref().duration;
unsafe {
@@ -1,5 +1,6 @@
use super::Entry;
use crate::wheel;
use crate::timer::timer::Entry;
use crate::timer::wheel;
use std::ptr;
use std::sync::Arc;
@@ -1,4 +1,5 @@
use crate::wheel::Stack;
use crate::timer::wheel::Stack;
use std::fmt;
/// Wheel for a single level in the timer. This wheel contains 64 slots.
@@ -1,8 +1,8 @@
mod level;
mod stack;
pub(crate) use self::level::Expiration;
use self::level::Level;
mod stack;
pub(crate) use self::stack::Stack;
use std::borrow::Borrow;
+2 -4
View File
@@ -1,17 +1,15 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "default")]
use tokio::runtime::{self, current_thread};
use tokio::timer::clock::Clock;
use tokio::timer::*;
use tokio_timer;
use tokio_timer::clock::Clock;
use std::sync::mpsc;
use std::time::{Duration, Instant};
struct MockNow(Instant);
impl tokio_timer::clock::Now for MockNow {
impl tokio::timer::clock::Now for MockNow {
fn now(&self) -> Instant {
self.0
}
@@ -1,8 +1,9 @@
#![warn(rust_2018_idioms)]
use tokio::timer::clock;
use tokio::timer::clock::*;
use std::time::Instant;
use tokio_timer::clock;
use tokio_timer::clock::*;
struct ConstNow(Instant);
@@ -1,11 +1,11 @@
#![warn(rust_2018_idioms)]
use std::time::{Duration, Instant};
use tokio::timer::delay;
use tokio::timer::timer::Handle;
use tokio_test::task::MockTask;
use tokio_test::{assert_pending, assert_ready, clock};
use tokio_timer::delay;
use tokio_timer::timer::Handle;
use std::time::{Duration, Instant};
#[test]
fn immediate_delay() {
@@ -1,8 +1,9 @@
#![warn(rust_2018_idioms)]
use tokio::timer::{Delay, Timer};
use tokio_executor::current_thread::CurrentThread;
use tokio_executor::park::{Park, Unpark, UnparkThread};
use tokio_timer::{Delay, Timer};
use rand;
use rand::Rng;
@@ -1,8 +1,8 @@
#![warn(rust_2018_idioms)]
use tokio::timer::*;
use tokio_test::task::MockTask;
use tokio_test::{assert_pending, assert_ready_eq, clock};
use tokio_timer::*;
use std::time::Duration;
@@ -1,8 +1,8 @@
#![warn(rust_2018_idioms)]
use tokio::timer::*;
use tokio_test::task::MockTask;
use tokio_test::{assert_ok, assert_pending, assert_ready, clock};
use tokio_timer::*;
use std::time::Duration;
@@ -1,5 +1,4 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "default")]
use tokio::prelude::*;
use tokio::timer::*;
@@ -1,10 +1,9 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "async-traits")]
use tokio_sync::mpsc;
use tokio::sync::mpsc;
use tokio::timer::throttle::Throttle;
use tokio_test::task::MockTask;
use tokio_test::{assert_pending, assert_ready_eq, clock};
use tokio_timer::throttle::Throttle;
use futures_core::Stream;
use std::time::Duration;
@@ -1,11 +1,11 @@
#![warn(rust_2018_idioms)]
use tokio_sync::oneshot;
use tokio::sync::oneshot;
use tokio::timer::*;
use tokio_test::task::MockTask;
use tokio_test::{
assert_err, assert_pending, assert_ready, assert_ready_err, assert_ready_ok, clock,
};
use tokio_timer::*;
use std::time::Duration;