mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-07 00:00:09 +02:00
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:
@@ -9,7 +9,6 @@ members = [
|
||||
"tokio-net",
|
||||
"tokio-sync",
|
||||
"tokio-test",
|
||||
"tokio-timer",
|
||||
"tokio-tls",
|
||||
"build-tests",
|
||||
]
|
||||
|
||||
@@ -70,8 +70,6 @@ jobs:
|
||||
tokio-sync:
|
||||
- async-traits
|
||||
tokio-macros: []
|
||||
tokio-timer:
|
||||
- async-traits
|
||||
tokio-test: []
|
||||
|
||||
# Test compilation failure
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -1,7 +1,7 @@
|
||||
//! Asynchronous values.
|
||||
|
||||
#[cfg(feature = "timer")]
|
||||
use tokio_timer::Timeout;
|
||||
use crate::timer::Timeout;
|
||||
|
||||
#[cfg(feature = "timer")]
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user