Compare commits

...
Author SHA1 Message Date
Carl Lerche 475dabe96d Release tokio v0.1.20, tokio-timer v0.2.21, and remove async-await-preview feature. (#1089)
The `async-await-preview` feature is removed as 0.1 will no longer track
Rust nightly.

This also bumps:
- tokio-timer (0.2.11).
2019-05-14 11:21:24 -07:00
Carl Lerche 951f2fd910 test: re-export macro dependencies (#1077)
Callers may not always have `futures` available at the root of the
crate. Re-exporting dependencies makes them available to the macro at a
deterministic location.
2019-05-03 20:43:40 -07:00
Carl Lerche 4ef736b9d5 async-await: add current_thread::Runtime::block_on_async (#1072)
This function is used by the Tokio macros introduced by #1058  but was
omitted from the PR.
2019-04-30 19:55:22 -07:00
Steven Fackler 219f24cbf1 timer: Replace Handle::deadline with Handle::timeout (#1074)
Deadline was deprecated a while ago and replaced with Timeout, but the
methods on Handle got missed.

Fixes #1071
2019-04-30 10:29:54 -07:00
Carl Lerche ea282efb2e ci: fix isRelease condition (#1066) 2019-04-29 10:37:00 -07:00
Michal 'vorner' Vaner 042224d33c signal: Smaller dependency (#1069)
The signal-hook library got split into lower-level and higher-level
parts. The tokio-signal uses only API from the lower-level one, so it
can depend on it directly.

The only effect of this change is smaller amount of compiled (and
unused) code during compilation. There's no change in the code actually
used.
2019-04-28 19:12:40 -07:00
Ian Hamlin 927eb80ad4 Fix an error in the mit-url in the README.md (#1068) 2019-04-27 12:56:40 -07:00
Carl Lerche 6a8934e897 Fix threadpool dependency (#1061) 2019-04-25 22:23:24 -04:00
Carl Lerche 0e400af78c Async/await polish (#1058)
A general refresh of Tokio's experimental async / await support.
2019-04-25 22:22:32 -04:00
Carl Lerche df702130d6 tcp: fix some tests that spuriously fail (#1060)
This does not remove all cases of using a fixed port in doc tests, but
removing some should reduce the likelihood of spurious failures.
2019-04-25 12:01:39 -07:00
Carl Lerche 949adbb887 chore: remember to remove path deps on release (#1057) 2019-04-24 10:42:39 -07:00
Ryan Dahl b2b796a228 rt: forward panic_handler to tokio::runtime::Builder (#1055) 2019-04-24 10:41:42 -07:00
Igor Gnatenko abb014efc2 tokio: Bump min version of tokio-sync (#1054)
It is needed for lock functionality which tokio now uses.
2019-04-24 08:24:59 -07:00
Lucio Franco e5cf0cc717 Introduce tokio-test crate (#1030) 2019-04-23 20:17:57 -07:00
87 changed files with 1275 additions and 297 deletions
+2 -2
View File
@@ -31,13 +31,13 @@ task:
folder: $HOME/.cargo/registry
test_script:
- . $HOME/.cargo/env
- cargo test --all --no-fail-fast
- cargo test --all
- (cd tokio-trace/test-log-support && cargo test)
- (cd tokio-trace/test_static_max_level_features && cargo test)
- cargo doc --all
i686_test_script:
- . $HOME/.cargo/env
- |
cargo test --all --exclude tokio-tls --no-fail-fast --target i686-unknown-freebsd
cargo test --all --exclude tokio-tls --exclude tokio-macros --target i686-unknown-freebsd
before_cache_script:
- rm -rf $HOME/.cargo/registry/index
+3 -1
View File
@@ -2,16 +2,18 @@
members = [
"tokio",
"tokio-async-await",
"tokio-buf",
"tokio-codec",
"tokio-current-thread",
"tokio-executor",
"tokio-fs",
"tokio-futures",
"tokio-io",
"tokio-macros",
"tokio-reactor",
"tokio-signal",
"tokio-sync",
"tokio-test",
"tokio-threadpool",
"tokio-timer",
"tokio-tcp",
+13 -10
View File
@@ -20,7 +20,7 @@ the Rust programming language. It is:
[crates-badge]: https://img.shields.io/crates/v/tokio.svg
[crates-url]: https://crates.io/crates/tokio
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
[mit-url]: LICENSE-MIT
[mit-url]: LICENSE
[azure-badge]: https://dev.azure.com/tokio-rs/Tokio/_apis/build/status/tokio-rs.tokio?branchName=master
[azure-url]: https://dev.azure.com/tokio-rs/Tokio/_build/latest?definitionId=1&branchName=master
[gitter-badge]: https://img.shields.io/gitter/room/tokio-rs/tokio.svg
@@ -28,7 +28,7 @@ the Rust programming language. It is:
[Website](https://tokio.rs) |
[Guides](https://tokio.rs/docs/getting-started/hello-world/) |
[API Docs](https://docs.rs/tokio/0.1.19/tokio) |
[API Docs](https://docs.rs/tokio/0.1.20/tokio) |
[Chat](https://gitter.im/tokio-rs/tokio)
The API docs for the master branch are published [here][master-dox].
@@ -49,9 +49,9 @@ level, it provides a few major components:
These components provide the runtime components necessary for building
an asynchronous application.
[net]: https://docs.rs/tokio/0.1.19/tokio/net/index.html
[reactor]: https://docs.rs/tokio/0.1.19/tokio/reactor/index.html
[scheduler]: https://docs.rs/tokio/0.1.19/tokio/runtime/index.html
[net]: https://docs.rs/tokio/0.1.20/tokio/net/index.html
[reactor]: https://docs.rs/tokio/0.1.20/tokio/reactor/index.html
[scheduler]: https://docs.rs/tokio/0.1.20/tokio/runtime/index.html
## Example
@@ -126,10 +126,6 @@ have greater guarantees of stability.
The crates included as part of Tokio are:
* [`tokio-async-await`]: Experimental `async` / `await` support.
* [`tokio-codec`]: Utilities for encoding and decoding protocol frames.
* [`tokio-current-thread`]: Schedule the execution of futures on the current
thread.
@@ -137,8 +133,14 @@ The crates included as part of Tokio are:
* [`tokio-fs`]: Filesystem (and standard in / out) APIs.
* [`tokio-futures`]: Experimental `std::future::Future` and `async` / `await` support.
* [`tokio-codec`]: Utilities for encoding and decoding protocol frames.
* [`tokio-io`]: Asynchronous I/O related traits and utilities.
* [`tokio-macros`]: Macros for usage with Tokio.
* [`tokio-reactor`]: Event loop that drives I/O resources (like TCP and UDP
sockets).
@@ -154,12 +156,13 @@ The crates included as part of Tokio are:
* [`tokio-uds`]: Unix Domain Socket bindings for use with `tokio-io` and
`tokio-reactor`.
[`tokio-async-await`]: tokio-async-await
[`tokio-codec`]: tokio-codec
[`tokio-current-thread`]: tokio-current-thread
[`tokio-executor`]: tokio-executor
[`tokio-fs`]: tokio-fs
[`tokio-futures`]: tokio-futures
[`tokio-io`]: tokio-io
[`tokio-macros`]: tokio-macros
[`tokio-reactor`]: tokio-reactor
[`tokio-tcp`]: tokio-tcp
[`tokio-threadpool`]: tokio-threadpool
+2
View File
@@ -0,0 +1,2 @@
[build]
target-dir = "../target"
+49
View File
@@ -0,0 +1,49 @@
[package]
name = "examples"
edition = "2018"
version = "0.1.0"
authors = ["Carl Lerche <[email protected]>"]
license = "MIT"
# Break out of the parent workspace
[workspace]
[[bin]]
name = "chat"
path = "src/chat.rs"
[[bin]]
name = "echo_client"
path = "src/echo_client.rs"
[[bin]]
name = "echo_server"
path = "src/echo_server.rs"
[[bin]]
name = "hyper"
path = "src/hyper.rs"
[dependencies]
tokio = { version = "0.1.18", features = ["async-await-preview"] }
futures = "0.1.23"
bytes = "0.4.9"
hyper = "0.12.8"
# Avoid using crates.io for Tokio dependencies
[patch.crates-io]
tokio = { path = "../tokio" }
tokio-codec = { path = "../tokio-codec" }
tokio-current-thread = { path = "../tokio-current-thread" }
tokio-executor = { path = "../tokio-executor" }
tokio-fs = { path = "../tokio-fs" }
tokio-futures = { path = "../tokio-futures" }
tokio-io = { path = "../tokio-io" }
tokio-reactor = { path = "../tokio-reactor" }
tokio-signal = { path = "../tokio-signal" }
tokio-tcp = { path = "../tokio-tcp" }
tokio-threadpool = { path = "../tokio-threadpool" }
tokio-timer = { path = "../tokio-timer" }
tokio-tls = { path = "../tokio-tls" }
tokio-udp = { path = "../tokio-udp" }
tokio-uds = { path = "../tokio-uds" }
@@ -1,9 +1,6 @@
#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
extern crate futures; // v0.1
#![feature(await_macro, async_await)]
use tokio::await;
use tokio::codec::{LinesCodec, Decoder};
use tokio::net::{TcpListener, TcpStream};
use tokio::prelude::*;
@@ -95,7 +92,8 @@ async fn process(stream: TcpStream, state: Arc<Mutex<Shared>>) -> io::Result<()>
Ok(())
}
fn main() {
#[tokio::main]
async fn main() {
// Create the shared state. This is how all the peers communicate.
//
// The server task will hold a handle to this. For every new client, the
@@ -113,23 +111,21 @@ fn main() {
println!("server running on localhost:6142");
// Start the Tokio runtime.
tokio::run_async(async move {
let mut incoming = listener.incoming();
let mut incoming = listener.incoming();
while let Some(stream) = await!(incoming.next()) {
let stream = match stream {
Ok(stream) => stream,
Err(_) => continue,
};
while let Some(stream) = await!(incoming.next()) {
let stream = match stream {
Ok(stream) => stream,
Err(_) => continue,
};
let state = state.clone();
let state = state.clone();
tokio::spawn_async(async move {
if let Err(_) = await!(process(stream, state)) {
eprintln!("failed to process connection");
}
});
}
});
tokio::spawn_async(async move {
if let Err(_) = await!(process(stream, state)) {
eprintln!("failed to process connection");
}
});
}
}
@@ -1,8 +1,6 @@
#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
#![feature(await_macro, async_await)]
use tokio::await;
use tokio::net::TcpStream;
use tokio::prelude::*;
@@ -36,7 +34,8 @@ async fn run_client(addr: &SocketAddr) -> io::Result<()> {
Ok(())
}
fn main() {
#[tokio::main]
async fn main() {
use std::env;
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
@@ -44,10 +43,8 @@ fn main() {
// Connect to the echo serveer
tokio::run_async(async move {
match await!(run_client(&addr)) {
Ok(_) => println!("done."),
Err(e) => eprintln!("echo client failed; error = {:?}", e),
}
});
match await!(run_client(&addr)) {
Ok(_) => println!("done."),
Err(e) => eprintln!("echo client failed; error = {:?}", e),
}
}
@@ -1,8 +1,6 @@
#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
#![feature(await_macro, async_await)]
use tokio::await;
use tokio::net::{TcpListener, TcpStream};
use tokio::prelude::*;
@@ -24,7 +22,8 @@ fn handle(mut stream: TcpStream) {
});
}
fn main() {
#[tokio::main]
async fn main() {
use std::env;
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
@@ -34,12 +33,10 @@ fn main() {
let listener = TcpListener::bind(&addr).unwrap();
println!("Listening on: {}", addr);
tokio::run_async(async {
let mut incoming = listener.incoming();
let mut incoming = listener.incoming();
while let Some(stream) = await!(incoming.next()) {
let stream = stream.unwrap();
handle(stream);
}
});
while let Some(stream) = await!(incoming.next()) {
let stream = stream.unwrap();
handle(stream);
}
}
+29
View File
@@ -0,0 +1,29 @@
#![feature(await_macro, async_await)]
use tokio::await;
use tokio::prelude::*;
use hyper::Client;
use std::time::Duration;
use std::str;
#[tokio::main]
async fn main() {
let client = Client::new();
let uri = "http://httpbin.org/ip".parse().unwrap();
let response = await!({
client.get(uri)
.timeout(Duration::from_secs(10))
}).unwrap();
println!("Response: {}", response.status());
let mut body = response.into_body();
while let Some(chunk) = await!(body.next()) {
let chunk = chunk.unwrap();
println!("chunk = {}", str::from_utf8(&chunk[..]).unwrap());
}
}
+22
View File
@@ -0,0 +1,22 @@
#![feature(await_macro, async_await)]
use tokio::await;
use tokio::timer::Delay;
use std::time::{Duration, Instant};
#[tokio::test]
async fn success_no_async() {
assert!(true);
}
#[tokio::test]
#[should_panic]
async fn fail_no_async() {
assert!(false);
}
#[tokio::test]
async fn use_timer() {
let when = Instant::now() + Duration::from_millis(10);
await!(Delay::new(when));
}
+9 -13
View File
@@ -1,5 +1,5 @@
trigger: ["master"]
pr: ["master"]
trigger: ["master", "v0.1.x"]
pr: ["master", "v0.1.x"]
jobs:
# Check formatting
@@ -45,6 +45,7 @@ jobs:
- tokio-sync
- tokio-threadpool
- tokio-timer
- tokio-test
- tokio-trace
- tokio-trace/tokio-trace-core
- tokio-trace/test-log-support
@@ -70,17 +71,12 @@ jobs:
tokio-buf:
- util
# Check async / await
- template: ci/azure-cargo-check.yml
# Run async-await tests
- template: ci/azure-test-nightly.yml
parameters:
name: async_await
displayName: Async / Await
rust: nightly-2019-04-22
noDefaultFeatures: ''
benches: true
crates:
tokio:
- async-await-preview
name: test_nightly
displayName: Test Async / Await
rust: nightly-2019-04-25
# Try cross compiling
- template: ci/azure-cross-compile.yml
@@ -112,7 +108,7 @@ jobs:
- test_sub_cross
- test_linux
- features
- async_await
- test_nightly
- cross_32bit_linux
- minrust
- tsan
-4
View File
@@ -27,7 +27,3 @@ jobs:
- script: cargo check ${{ parameters.noDefaultFeatures }} --features ${{ feature }}
displayName: Check `${{ crate.key }}`, features = ${{ feature }}
workingDirectory: $(Build.SourcesDirectory)/${{ crate.key }}
- ${{ if parameters.benches }}:
- script: cargo check --benches --all
displayName: Check benchmarks
+1 -1
View File
@@ -2,7 +2,7 @@ steps:
- bash: |
set -e
if git log --no-merges -1 --format='%s' | grep -q '[ci-release]'; then
if git log --no-merges -1 --format='%B' | grep -qF '[ci-release]'; then
echo "##vso[task.setvariable variable=isRelease]true"
fi
failOnStderr: true
+19
View File
@@ -0,0 +1,19 @@
jobs:
- job: ${{ parameters.name }}
displayName: ${{ parameters.displayName }}
pool:
vmImage: ubuntu-16.04
steps:
- template: azure-install-rust.yml
parameters:
rust_version: ${{ parameters.rust }}
- template: azure-patch-crates.yml
- script: cargo check --all
displayName: cargo +nightly check --all
# Check benches
- script: cargo check --benches --all
displayName: Check benchmarks
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
CI: 'True'
displayName: cargo test -p ${{ crate }}
workingDirectory: $(Build.SourcesDirectory)/${{ crate }}
condition: and(succeeded(), not(variables['isRelease']))
condition: and(succeeded(), ne(variables['isRelease'], 'true'))
- template: azure-patch-crates.yml
+1 -1
View File
@@ -2,12 +2,12 @@
# repository.
[patch.crates-io]
tokio = { path = "tokio" }
tokio-async-await = { path = "tokio-async-await" }
tokio-buf = { path = "tokio-buf" }
tokio-codec = { path = "tokio-codec" }
tokio-current-thread = { path = "tokio-current-thread" }
tokio-executor = { path = "tokio-executor" }
tokio-fs = { path = "tokio-fs" }
tokio-futures = { path = "tokio-futures" }
tokio-io = { path = "tokio-io" }
tokio-reactor = { path = "tokio-reactor" }
tokio-signal = { path = "tokio-signal" }
-2
View File
@@ -1,2 +0,0 @@
[build]
target-dir = "../../target"
-49
View File
@@ -1,49 +0,0 @@
[package]
name = "examples"
edition = "2018"
version = "0.1.0"
authors = ["Carl Lerche <[email protected]>"]
license = "MIT"
# Break out of the parent workspace
[workspace]
[[bin]]
name = "chat"
path = "src/chat.rs"
[[bin]]
name = "echo_client"
path = "src/echo_client.rs"
[[bin]]
name = "echo_server"
path = "src/echo_server.rs"
[[bin]]
name = "hyper"
path = "src/hyper.rs"
[dependencies]
tokio = { version = "0.1.18", features = ["async-await-preview"] }
futures = "0.1.23"
bytes = "0.4.9"
hyper = "0.12.8"
# Avoid using crates.io for Tokio dependencies
[patch.crates-io]
tokio = { path = "../../tokio" }
tokio-async-await = { path = "../" }
tokio-codec = { path = "../../tokio-codec" }
tokio-current-thread = { path = "../../tokio-current-thread" }
tokio-executor = { path = "../../tokio-executor" }
tokio-fs = { path = "../../tokio-fs" }
tokio-io = { path = "../../tokio-io" }
tokio-reactor = { path = "../../tokio-reactor" }
tokio-signal = { path = "../../tokio-signal" }
tokio-tcp = { path = "../../tokio-tcp" }
tokio-threadpool = { path = "../../tokio-threadpool" }
tokio-timer = { path = "../../tokio-timer" }
tokio-tls = { path = "../../tokio-tls" }
tokio-udp = { path = "../../tokio-udp" }
tokio-uds = { path = "../../tokio-uds" }
-33
View File
@@ -1,33 +0,0 @@
#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
extern crate hyper;
use tokio::prelude::*;
use hyper::Client;
use std::time::Duration;
use std::str;
pub fn main() {
tokio::run_async(async {
let client = Client::new();
let uri = "http://httpbin.org/ip".parse().unwrap();
let response = await!({
client.get(uri)
.timeout(Duration::from_secs(10))
}).unwrap();
println!("Response: {}", response.status());
let mut body = response.into_body();
while let Some(chunk) = await!(body.next()) {
let chunk = chunk.unwrap();
println!("chunk = {}", str::from_utf8(&chunk[..]).unwrap());
}
});
}
-4
View File
@@ -1,4 +0,0 @@
#![doc(hidden)]
pub mod backward;
pub mod forward;
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "tokio-buf"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+4 -2
View File
@@ -1,9 +1,11 @@
[package]
name = "tokio-codec"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc URL.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.1"
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "tokio-current-thread"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+3 -3
View File
@@ -1,12 +1,12 @@
[package]
name = "tokio-executor"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update CHANGELOG.md.
# - Update doc URL.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.7"
documentation = "https://docs.rs/tokio-executor/0.1.7/tokio_executor"
+3 -3
View File
@@ -1,12 +1,12 @@
[package]
name = "tokio-fs"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update CHANGELOG.md.
# - Update doc URL.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.6"
authors = ["Carl Lerche <[email protected]>"]
@@ -1,16 +1,16 @@
[package]
name = "tokio-async-await"
name = "tokio-futures"
# When releasing to crates.io:
# - Update html_root_url.
version = "0.1.7"
version = "0.1.0"
authors = ["Carl Lerche <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://tokio.rs"
documentation = "https://docs.rs/tokio-async-await/0.1.7"
documentation = "https://docs.rs/tokio-futures/0.1.0"
description = """
Experimental async/await support for Tokio
Experimental std::future::Future and async/await support for Tokio
"""
categories = ["asynchronous"]
@@ -25,5 +25,5 @@ tokio-io = "0.1.7"
[dev-dependencies]
bytes = "0.4.9"
tokio = "0.1.8"
hyper = "0.12.8"
tokio = { version = "0.1.8", path = "../tokio" }
@@ -25,9 +25,9 @@ Then, get started. In your application, add:
```rust
// The nightly features that are commonly needed with async / await
#![feature(await_macro, async_await, futures_api)]
#![feature(await_macro, async_await)]
// This pulls in the `tokio-async-await` crate. While Rust 2018 doesn't require
// This pulls in the `tokio-futures` crate. While Rust 2018 doesn't require
// `extern crate`, we need to pull in the macros.
#[macro_use]
extern crate tokio;
@@ -1,3 +1,5 @@
//! Converts a `std::future::Future` into an 0.1 `Future.
use futures::{Future, Poll};
use std::future::Future as StdFuture;
@@ -5,18 +7,18 @@ use std::pin::Pin;
use std::ptr;
use std::task::{Context, Poll as StdPoll, RawWaker, RawWakerVTable, Waker};
/// Convert an 0.3 `Future` to an 0.1 `Future`.
/// Converts a `std::future::Future` into an 0.1 `Future.
#[derive(Debug)]
pub struct Compat<T>(Pin<Box<T>>);
impl<T> Compat<T> {
/// Create a new `Compat` backed by `future`.
pub fn new(future: T) -> Compat<T> {
pub(crate) fn new(future: T) -> Compat<T> {
Compat(Box::pin(future))
}
}
/// Convert a value into one that can be used with `await!`.
#[doc(hidden)]
pub trait IntoAwaitable {
type Awaitable;
@@ -74,7 +76,11 @@ unsafe fn clone_raw(_data: *const ()) -> RawWaker {
unsafe fn drop_raw(_data: *const ()) {}
unsafe fn wake(_data: *const ()) {
unimplemented!("async-await-preview currently only supports futures 0.1. Use the compatibility layer of futures 0.3 instead, if you want to use futures 0.3.");
unimplemented!(
"async-await-preview currently only supports futures 0.1. Use \
the compatibility layer of futures 0.3 instead, if you want \
to use futures 0.3."
);
}
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake, wake, drop_raw);
@@ -1,10 +1,12 @@
//! Converts an 0.1 `Future` into a `std::future::Future`.
//!
use futures::{Async, Future};
use std::future::Future as StdFuture;
use std::pin::Pin;
use std::task::{Context, Poll as StdPoll};
/// Converts an 0.1 `Future` into an 0.3 `Future`.
/// Converts an 0.1 `Future` into a `std::future::Future`.
#[derive(Debug)]
pub struct Compat<T>(T);
@@ -31,7 +33,7 @@ pub(crate) fn convert_poll_stream<T, E>(
}
}
/// Convert a value into one that can be used with `await!`.
#[doc(hidden)]
pub trait IntoAwaitable {
type Awaitable;
+42
View File
@@ -0,0 +1,42 @@
//! Compatibility layer between futures 0.1 and `std`.
pub mod backward;
pub mod forward;
/// Convert a `std::future::Future` yielding `Result` into an 0.1 `Future`.
pub fn into_01<T, Item, Error>(future: T) -> backward::Compat<T>
where
T: std::future::Future<Output = Result<Item, Error>>,
{
backward::Compat::new(future)
}
/// Convert a `std::future::Future` into an 0.1 `Future` with unit error.
pub fn infallible_into_01<T>(future: T) -> impl futures::Future<Item = T::Output, Error = ()>
where
T: std::future::Future,
{
use std::pin::Pin;
use std::task::{Context, Poll};
pub struct Map<T>(T);
impl<T> Map<T> {
fn future<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) }
}
}
impl<T: std::future::Future> std::future::Future for Map<T> {
type Output = Result<T::Output, ()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
match self.future().poll(cx) {
Poll::Ready(v) => Poll::Ready(Ok(v)),
Poll::Pending => Poll::Pending,
}
}
}
into_01(Map(future))
}
@@ -25,7 +25,7 @@ pub trait AsyncReadExt: AsyncRead {
/// # Examples
///
/// ```edition2018
/// #![feature(async_await, await_macro, futures_api)]
/// #![feature(async_await, await_macro)]
/// tokio::run_async(async {
/// // The extension trait can also be imported with
/// // `use tokio::prelude::*`.
@@ -59,7 +59,7 @@ pub trait AsyncReadExt: AsyncRead {
/// # Examples
///
/// ```edition2018
/// #![feature(async_await, await_macro, futures_api)]
/// #![feature(async_await, await_macro)]
/// tokio::run_async(async {
/// // The extension trait can also be imported with
/// // `use tokio::prelude::*`.
@@ -78,7 +78,7 @@ pub trait AsyncReadExt: AsyncRead {
/// ## EOF is hit before `buf` is filled
///
/// ```edition2018
/// #![feature(async_await, await_macro, futures_api)]
/// #![feature(async_await, await_macro)]
/// tokio::run_async(async {
/// // The extension trait can also be imported with
/// // `use tokio::prelude::*`.
@@ -110,7 +110,7 @@ pub trait AsyncWriteExt: AsyncWrite {
/// # Examples
///
/// ```edition2018
/// #![feature(async_await, await_macro, futures_api)]
/// #![feature(async_await, await_macro)]
/// tokio::run_async(async {
/// // The extension trait can also be imported with
/// // `use tokio::prelude::*`.
@@ -139,7 +139,7 @@ pub trait AsyncWriteExt: AsyncWrite {
/// # Examples
///
/// ```edition2018
/// #![feature(async_await, await_macro, futures_api)]
/// #![feature(async_await, await_macro)]
/// tokio::run_async(async {
/// // The extension trait can also be imported with
/// // `use tokio::prelude::*`.
@@ -163,7 +163,7 @@ pub trait AsyncWriteExt: AsyncWrite {
/// # Examples
///
/// ```edition2018
/// #![feature(async_await, await_macro, futures_api)]
/// #![feature(async_await, await_macro)]
/// tokio::run_async(async {
/// // The extension trait can also be imported with
/// // `use tokio::prelude::*`.
@@ -1,6 +1,6 @@
#![cfg(feature = "async-await-preview")]
#![feature(rust_2018_preview, async_await, await_macro, futures_api)]
#![doc(html_root_url = "https://docs.rs/tokio-async-await/0.1.7")]
#![feature(await_macro)]
#![doc(html_root_url = "https://docs.rs/tokio-futures/0.1.0")]
#![deny(missing_docs, missing_debug_implementations)]
#![cfg_attr(test, deny(warnings))]
@@ -13,7 +13,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```edition2018
/// #![feature(await_macro, async_await, futures_api)]
/// #![feature(await_macro, async_await)]
/// tokio::run_async(async {
/// // The extension trait can also be imported with
/// // `use tokio::prelude::*`.
+4 -4
View File
@@ -1,12 +1,12 @@
[package]
name = "tokio-io"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update CHANGELOG.md.
# - Update doc URL.
# - Update doc url
# - Cargo.toml
# - Readme.md
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.12"
authors = ["Carl Lerche <[email protected]>"]
+27
View File
@@ -0,0 +1,27 @@
[package]
name = "tokio-macros"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
edition = "2018"
publish = false
[lib]
proc-macro = true
[features]
# This feature comes with no promise of stability. Things will
# break with each patch release. Use at your own risk.
async-await-preview = []
[dependencies]
proc-macro2 = "0.4.27"
quote = "0.6.11"
syn = { version = "0.15.27", features = ["full", "extra-traits", "visit-mut"] }
+47
View File
@@ -0,0 +1,47 @@
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.
The MIT License (MIT)
Copyright (c) 2019 Yoshua Wuyts
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
@@ -0,0 +1,13 @@
# Tokio Macros
Procedural macros for use with 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.
+81
View File
@@ -0,0 +1,81 @@
#![cfg(feature = "async-await-preview")]
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
/// Define the program entry point
///
/// # Examples
///
/// ```
/// #[tokio::main]
/// async fn main() {
/// println!("Hello world");
/// }
#[proc_macro_attribute]
pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as syn::ItemFn);
let ret = &input.decl.output;
let name = &input.ident;
let body = &input.block;
if input.asyncness.is_none() {
let tokens = quote_spanned! { input.span() =>
compile_error!("the async keyword is missing from the function declaration");
};
return TokenStream::from(tokens);
}
let result = quote! {
fn #name() #ret {
let mut rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on_async(async { #body })
}
};
result.into()
}
/// Define a Tokio aware unit test
///
/// # Examples
///
/// ```
/// #[tokio::test]
/// async fn my_test() {
/// assert!(true);
/// }
/// ```
#[proc_macro_attribute]
pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as syn::ItemFn);
let ret = &input.decl.output;
let name = &input.ident;
let body = &input.block;
let attrs = &input.attrs;
if input.asyncness.is_none() {
let tokens = quote_spanned! { input.span() =>
compile_error!("the async keyword is missing from the function declaration");
};
return TokenStream::from(tokens);
}
let result = quote! {
#[test]
#(#attrs)*
fn #name() #ret {
let mut rt = tokio::runtime::current_thread::Runtime::new().unwrap();
rt.block_on_async(async { #body })
}
};
result.into()
}
+3 -3
View File
@@ -1,12 +1,12 @@
[package]
name = "tokio-reactor"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update CHANGELOG.md.
# - Update doc URL.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.9"
authors = ["Carl Lerche <[email protected]>"]
+5 -3
View File
@@ -1,10 +1,12 @@
[package]
name = "tokio-signal"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Update doc URL.
# - Create "v0.2.x" git tag.
version = "0.2.8"
authors = ["Tokio Contributors <[email protected]>"]
@@ -31,7 +33,7 @@ tokio-io = "0.1"
[target.'cfg(unix)'.dependencies]
libc = "0.2"
mio-uds = "0.6"
signal-hook = "0.1"
signal-hook-registry = "~1"
[dev-dependencies]
tokio = "0.1.8"
+4 -3
View File
@@ -8,7 +8,7 @@
pub extern crate libc;
extern crate mio;
extern crate mio_uds;
extern crate signal_hook;
extern crate signal_hook_registry;
use std::io::prelude::*;
use std::io::{self, Error, ErrorKind};
@@ -153,7 +153,7 @@ fn action(slot: &SignalInfo, mut sender: &UnixStream) {
/// This will register the signal handler if it hasn't already been registered,
/// returning any error along the way if that fails.
fn signal_enable(signal: c_int) -> io::Result<()> {
if signal_hook::FORBIDDEN.contains(&signal) {
if signal_hook_registry::FORBIDDEN.contains(&signal) {
return Err(Error::new(
ErrorKind::Other,
format!("Refusing to register signal {}", signal),
@@ -168,7 +168,8 @@ fn signal_enable(signal: c_int) -> io::Result<()> {
let mut registered = Ok(());
siginfo.init.call_once(|| {
registered = unsafe {
signal_hook::register(signal, move || action(siginfo, &globals.sender)).map(|_| ())
signal_hook_registry::register(signal, move || action(siginfo, &globals.sender))
.map(|_| ())
};
if registered.is_ok() {
siginfo.initialized.store(true, Ordering::Relaxed);
+1
View File
@@ -1,6 +1,7 @@
[package]
name = "tokio-sync"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "tokio-tcp"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+7 -7
View File
@@ -61,7 +61,7 @@ impl TcpListener {
/// use tokio::net::TcpListener;
///
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
/// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
/// let listener = TcpListener::bind(&addr)?;
/// # Ok(())
/// # }
@@ -109,7 +109,7 @@ impl TcpListener {
/// use futures::Async;
///
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
/// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
/// let mut listener = TcpListener::bind(&addr)?;
/// match listener.poll_accept() {
/// Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
@@ -167,7 +167,7 @@ impl TcpListener {
/// use futures::Async;
///
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
/// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
/// let mut listener = TcpListener::bind(&addr)?;
/// match listener.poll_accept_std() {
/// Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
@@ -230,7 +230,7 @@ impl TcpListener {
/// use tokio::reactor::Handle;
///
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// let std_listener = StdTcpListener::bind("127.0.0.1:8080")?;
/// let std_listener = StdTcpListener::bind("127.0.0.1:0")?;
/// let listener = TcpListener::from_std(std_listener, &Handle::default())?;
/// # Ok(())
/// # }
@@ -296,7 +296,7 @@ impl TcpListener {
/// use std::net::SocketAddr;
///
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
/// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
/// let listener = TcpListener::bind(&addr)?;
///
/// listener.incoming()
@@ -326,7 +326,7 @@ impl TcpListener {
/// use std::net::SocketAddr;
///
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
/// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
/// let listener = TcpListener::bind(&addr)?;
/// listener.set_ttl(100).expect("could not set TTL");
/// assert_eq!(listener.ttl()?, 100);
@@ -350,7 +350,7 @@ impl TcpListener {
/// use std::net::SocketAddr;
///
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
/// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
/// let listener = TcpListener::bind(&addr)?;
/// listener.set_ttl(100).expect("could not set TTL");
/// # Ok(())
+1
View File
@@ -0,0 +1 @@
+26
View File
@@ -0,0 +1,26 @@
[package]
name = "tokio-test"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://tokio.rs"
documentation = "https://docs.rs/tokio-test/0.1.0/tokio_test"
description = """
Testing utilities for Tokio- and futures-based code
"""
categories = ["asynchronous", "testing"]
publish = false
[dependencies]
futures = "0.1"
tokio-timer = "0.2"
tokio-executor = "0.1"
+25
View File
@@ -0,0 +1,25 @@
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.
+36
View File
@@ -0,0 +1,36 @@
# tokio-test
Tokio and Futures based testing utilities
[Documenation](https://docs.rs/tokio-test)
## Usage
First, add this to your `Cargo.toml`:
```toml
[dev-dependencies]
tokio-test = "0.1.0"
```
Next, add this to your crate:
```rust
#[macro_use]
extern crate tokio_test;
```
You can find extensive documentation and examples about how to use this crate
online at [https://tokio.rs](https://tokio.rs). The [API
documentation](https://docs.rs/tokio-test) is also a great place to get started
for the nitty-gritty.
## 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.
+256
View File
@@ -0,0 +1,256 @@
//! A mocked clock for use with `tokio_timer` based futures.
//!
//! # Example
//!
//! ```
//! # #[macro_use] extern crate tokio_test;
//! # extern crate futures;
//! # extern crate tokio_timer;
//! # use tokio_test::clock;
//! # use tokio_timer::Delay;
//! # use std::time::Duration;
//! # use futures::Future;
//! clock::mock(|handle| {
//! let mut delay = Delay::new(handle.now() + Duration::from_secs(1));
//!
//! assert_not_ready!(delay.poll());
//!
//! handle.advance(Duration::from_secs(1));
//!
//! assert_ready!(delay.poll());
//! });
//! ```
use futures::{future::lazy, Future};
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use tokio_executor::park::{Park, Unpark};
use tokio_timer::clock::{Clock, Now};
use tokio_timer::Timer;
/// Run the provided closure with a `MockClock` that starts at the current time.
pub fn mock<F, R>(f: F) -> R
where
F: FnOnce(&mut Handle) -> R,
{
let mut mock = MockClock::new();
mock.enter(f)
}
/// Run the provided closure with a `MockClock` that starts at the provided `Instant`.
pub fn mock_at<F, R>(instant: Instant, f: F) -> R
where
F: FnOnce(&mut Handle) -> R,
{
let mut mock = MockClock::with_instant(instant);
mock.enter(f)
}
/// Mock clock for use with `tokio-timer` futures.
///
/// A mock timer that is able to advance and wake after a
/// certain duration.
#[derive(Debug)]
pub struct MockClock {
time: MockTime,
clock: Clock,
}
/// A handle to the `MockClock`.
#[derive(Debug)]
pub struct Handle {
timer: Timer<MockPark>,
time: MockTime,
}
type Inner = Arc<Mutex<State>>;
#[derive(Debug, Clone)]
struct MockTime {
inner: Inner,
_pd: PhantomData<Rc<()>>,
}
#[derive(Debug)]
struct MockNow {
inner: Inner,
}
#[derive(Debug)]
struct MockPark {
inner: Inner,
_pd: PhantomData<Rc<()>>,
}
#[derive(Debug)]
struct MockUnpark {
inner: Inner,
}
#[derive(Debug)]
struct State {
base: Instant,
advance: Duration,
unparked: bool,
park_for: Option<Duration>,
}
impl MockClock {
/// Create a new `MockClock` with the current time.
pub fn new() -> Self {
MockClock::with_instant(Instant::now())
}
/// Create a `MockClock` with its current time at a duration from now
///
/// This will create a clock with `Instant::now() + duration` as the current time.
pub fn with_duration(duration: Duration) -> Self {
let instant = Instant::now() + duration;
MockClock::with_instant(instant)
}
/// Create a `MockClock` that sets its current time as the `Instant` provided.
pub fn with_instant(instant: Instant) -> Self {
let time = MockTime::new(instant);
let clock = Clock::new_with_now(time.mock_now());
MockClock { time, clock }
}
/// Enter the `MockClock` context.
pub fn enter<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut Handle) -> R,
{
let mut enter = ::tokio_executor::enter().unwrap();
::tokio_timer::clock::with_default(&self.clock, &mut enter, |enter| {
let park = self.time.mock_park();
let timer = Timer::new(park);
let handle = timer.handle();
let time = self.time.clone();
::tokio_timer::with_default(&handle, enter, |_| {
let mut handle = Handle::new(timer, time);
lazy(|| Ok::<_, ()>(f(&mut handle))).wait().unwrap()
})
})
}
}
impl Handle {
pub(self) fn new(timer: Timer<MockPark>, time: MockTime) -> Self {
Handle { timer, time }
}
/// Turn the internal timer and mock park for the provided duration.
pub fn turn(&mut self, duration: Option<Duration>) {
self.timer.turn(duration).unwrap();
}
/// Advance the `MockClock` by the provided duration.
pub fn advance(&mut self, duration: Duration) {
let inner = self.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();
self.turn(Some(dur));
}
}
/// Get the currently mocked time
pub fn now(&mut self) -> Instant {
self.time.now()
}
}
impl MockTime {
pub(crate) 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)),
_pd: PhantomData,
}
}
pub(crate) fn mock_now(&self) -> MockNow {
let inner = self.inner.clone();
MockNow { inner }
}
pub(crate) fn mock_park(&self) -> MockPark {
let inner = self.inner.clone();
MockPark {
inner,
_pd: PhantomData,
}
}
pub(crate) 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;
}
}
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()
}
}
+30
View File
@@ -0,0 +1,30 @@
#![doc(html_root_url = "https://docs.rs/tokio-test/0.1.0")]
#![deny(missing_docs, missing_debug_implementations, unreachable_pub)]
#![cfg_attr(test, deny(warnings))]
//! Tokio and Futures based testing utilites
//!
//! # Example
//!
//! ```
//! # extern crate futures;
//! # #[macro_use] extern crate tokio_test;
//! # use futures::{Future, future};
//! let mut fut = future::ok::<(), ()>(());
//! assert_ready!(fut.poll());
//! ```
extern crate futures;
extern crate tokio_executor;
extern crate tokio_timer;
pub mod clock;
mod macros;
pub mod task;
#[doc(hidden)]
pub mod codegen {
pub mod futures {
pub use futures::*;
}
}
+131
View File
@@ -0,0 +1,131 @@
//! A collection of useful macros for testing futures and tokio based code
/// Assert if a poll is ready
#[macro_export]
macro_rules! assert_ready {
($e:expr) => {{
use $crate::codegen::futures::Async::Ready;
match $e {
Ok(Ready(v)) => v,
Ok(_) => panic!("not ready"),
Err(e) => panic!("error = {:?}", e),
}
}};
($e:expr, $($msg:tt),+) => {{
use $crate::codegen::futures::Async::Ready;
match $e {
Ok(Ready(v)) => v,
Ok(_) => {
let msg = format_args!($($msg),+);
panic!("not ready; {}", msg)
}
Err(e) => {
let msg = format!($($msg),+);
panic!("error = {:?}; {}", e, msg)
}
}
}};
}
/// Asset if the poll is not ready
#[macro_export]
macro_rules! assert_not_ready {
($e:expr) => {{
use $crate::codegen::futures::Async::{Ready, NotReady};
match $e {
Ok(NotReady) => {}
Ok(Ready(v)) => panic!("ready; value = {:?}", v),
Err(e) => panic!("error = {:?}", e),
}
}};
($e:expr, $($msg:tt),+) => {{
use $crate::codegen::futures::Async::{Ready, NotReady};
match $e {
Ok(NotReady) => {}
Ok(Ready(v)) => {
let msg = format_args!($($msg),+);
panic!("ready; value = {:?}; {}", v, msg)
}
Err(e) => {
let msg = format_args!($($msg),+);
panic!("error = {:?}; {}", e, msg)
}
}
}};
}
/// Assert if a poll is ready and check for equality on the value
#[macro_export]
macro_rules! assert_ready_eq {
($e:expr, $expect:expr) => {
use $crate::codegen::futures::Async::Ready;
match $e {
Ok(e) => assert_eq!(e, Ready($expect)),
Err(e) => panic!("error = {:?}", e),
}
};
($e:expr, $expect:expr, $($msg:tt),+) => {
use $crate::codegen::futures::Async::Ready;
match $e {
Ok(e) => assert_eq!(e, Ready($expect), $($msg)+),
Err(e) => {
let msg = format_args!($($msg),+);
panic!("error = {:?}; {}", e, msg)
}
}
};
}
/// Assert if the deadline has passed
#[macro_export]
macro_rules! assert_elapsed {
($e:expr) => {
assert!($e.unwrap_err().is_elapsed());
};
($e:expr, $($msg:expr),+) => {
assert!($e.unwrap_err().is_elapsed(), $msg);
};
}
#[cfg(test)]
mod tests {
use futures::{future, Async, Future, Poll};
#[test]
fn assert_ready() {
let mut fut = future::ok::<(), ()>(());
assert_ready!(fut.poll());
let mut fut = future::ok::<(), ()>(());
assert_ready!(fut.poll(), "some message");
}
#[test]
#[should_panic]
fn assert_ready_err() {
let mut fut = future::err::<(), ()>(());
assert_ready!(fut.poll());
}
#[test]
fn assert_not_ready() {
let poll: Poll<(), ()> = Ok(Async::NotReady);
assert_not_ready!(poll);
assert_not_ready!(poll, "some message");
}
#[test]
#[should_panic]
fn assert_not_ready_err() {
let mut fut = future::err::<(), ()>(());
assert_not_ready!(fut.poll());
}
#[test]
fn assert_ready_eq() {
let mut fut = future::ok::<(), ()>(());
assert_ready_eq!(fut.poll(), ());
}
}
+133
View File
@@ -0,0 +1,133 @@
//! Futures task based helpers
//!
//! # Example
//!
//! This example will use the `MockTask` to set the current task on
//! poll.
//!
//! ```
//! # #[macro_use] extern crate tokio_test;
//! # extern crate futures;
//! # use tokio_test::task::MockTask;
//! # use futures::{sync::mpsc, Stream, Sink, Future, Async};
//! let mut task = MockTask::new();
//! let (tx, mut rx) = mpsc::channel(5);
//!
//! tx.send(()).wait();
//!
//! assert_ready_eq!(task.enter(|| rx.poll()), Some(()));
//! ```
use futures::executor::{spawn, Notify};
use futures::{future, Async};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Condvar, Mutex};
/// Mock task
///
/// A mock task is able to intercept and track notifications.
#[derive(Debug)]
pub struct MockTask {
notify: Arc<ThreadNotify>,
}
#[derive(Debug)]
struct ThreadNotify {
state: AtomicUsize,
mutex: Mutex<()>,
condvar: Condvar,
}
const IDLE: usize = 0;
const NOTIFY: usize = 1;
const SLEEP: usize = 2;
impl MockTask {
/// Create a new mock task
pub fn new() -> Self {
MockTask {
notify: Arc::new(ThreadNotify::new()),
}
}
/// Run a closure from the context of the task.
///
/// Any notifications resulting from the execution of the closure are
/// tracked.
pub fn enter<F, R>(&mut self, f: F) -> R
where
F: FnOnce() -> R,
{
self.notify.clear();
let res = spawn(future::lazy(|| Ok::<_, ()>(f()))).poll_future_notify(&self.notify, 0);
match res.unwrap() {
Async::Ready(v) => v,
_ => unreachable!(),
}
}
/// Returns `true` if the inner future has received a readiness notification
/// since the last call to `enter`.
pub fn is_notified(&self) -> bool {
self.notify.is_notified()
}
/// Returns the number of references to the task notifier
///
/// The task itself holds a reference. The return value will never be zero.
pub fn notifier_ref_count(&self) -> usize {
Arc::strong_count(&self.notify)
}
}
impl ThreadNotify {
fn new() -> Self {
ThreadNotify {
state: AtomicUsize::new(IDLE),
mutex: Mutex::new(()),
condvar: Condvar::new(),
}
}
/// Clears any previously received notify, avoiding potential spurrious
/// notifications. This should only be called immediately before running the
/// task.
fn clear(&self) {
self.state.store(IDLE, Ordering::SeqCst);
}
fn is_notified(&self) -> bool {
match self.state.load(Ordering::SeqCst) {
IDLE => false,
NOTIFY => true,
_ => unreachable!(),
}
}
}
impl Notify for ThreadNotify {
fn notify(&self, _unpark_id: usize) {
// First, try transitioning from IDLE -> NOTIFY, this does not require a
// lock.
match self.state.compare_and_swap(IDLE, NOTIFY, Ordering::SeqCst) {
IDLE | NOTIFY => return,
SLEEP => {}
_ => unreachable!(),
}
// The other half is sleeping, this requires a lock
let _m = self.mutex.lock().unwrap();
// Transition from SLEEP -> NOTIFY
match self.state.compare_and_swap(SLEEP, NOTIFY, Ordering::SeqCst) {
SLEEP => {}
_ => return,
}
// Wakeup the sleeper
self.condvar.notify_one();
}
}
+44
View File
@@ -0,0 +1,44 @@
#[macro_use]
extern crate tokio_test;
extern crate futures;
extern crate tokio_timer;
use futures::Future;
use std::time::{Duration, Instant};
use tokio_test::clock::MockClock;
use tokio_test::task::MockTask;
use tokio_timer::Delay;
#[test]
fn clock() {
let mut mock = MockClock::new();
mock.enter(|handle| {
let deadline = Instant::now() + Duration::from_secs(1);
let mut delay = Delay::new(deadline);
assert_not_ready!(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::new(deadline);
task.enter(|| assert_not_ready!(delay.poll()));
handle.advance(Duration::from_secs(1));
assert!(task.is_notified());
assert_ready!(delay.poll());
});
}
+1
View File
@@ -1,6 +1,7 @@
[package]
name = "tokio-threadpool"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+5
View File
@@ -1,3 +1,8 @@
# 0.2.11 (May 14, 2019)
### Added
- `Handle::timeout` API, replacing the deprecated `Handle::deadline` (#1074).
# 0.2.10 (February 4, 2019)
### Fixed
+3 -2
View File
@@ -1,17 +1,18 @@
[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.2.x" git tag.
version = "0.2.10"
version = "0.2.11"
authors = ["Carl Lerche <[email protected]>"]
license = "MIT"
readme = "README.md"
documentation = "https://docs.rs/tokio-timer/0.2.10/tokio_timer"
documentation = "https://docs.rs/tokio-timer/0.2.11/tokio_timer"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://github.com/tokio-rs/tokio"
description = """
+1 -1
View File
@@ -2,7 +2,7 @@
Timer facilities for Tokio
[Documentation](https://docs.rs/tokio-timer/0.2.10/tokio_timer/)
[Documentation](https://docs.rs/tokio-timer/0.2.11/tokio_timer/)
## Overview
+1 -1
View File
@@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/tokio-timer/0.2.10")]
#![doc(html_root_url = "https://docs.rs/tokio-timer/0.2.11")]
#![deny(missing_docs, warnings, missing_debug_implementations)]
//! Utilities for tracking time.
+3
View File
@@ -126,7 +126,10 @@ impl<T> Timeout<T> {
/// ```
pub fn new(value: T, timeout: Duration) -> Timeout<T> {
let delay = Delay::new_timeout(now() + timeout, timeout);
Timeout::new_with_delay(value, delay)
}
pub(crate) fn new_with_delay(value: T, delay: Delay) -> Timeout<T> {
Timeout { value, delay }
}
+8 -2
View File
@@ -1,5 +1,5 @@
use timer::Inner;
use {Deadline, Delay, Error, Interval};
use {Deadline, Delay, Error, Interval, Timeout};
use tokio_executor::Enter;
@@ -139,11 +139,17 @@ impl Handle {
}
}
/// Create a `Deadline` driven by this handle's associated `Timer`.
#[doc(hidden)]
#[deprecated(since = "0.2.11", note = "use timeout instead")]
pub fn deadline<T>(&self, future: T, deadline: Instant) -> Deadline<T> {
Deadline::new_with_delay(future, self.delay(deadline))
}
/// Create a `Timeout` driven by this handle's associated `Timer`.
pub fn timeout<T>(&self, value: T, deadline: Instant) -> Timeout<T> {
Timeout::new_with_delay(value, self.delay(deadline))
}
/// Create a new `Interval` that starts at `at` and yields every `duration`
/// interval after that.
pub fn interval(&self, at: Instant, duration: Duration) -> Interval {
+1 -1
View File
@@ -118,7 +118,7 @@ fn hammer_cancel() {
let deadline = cmp::min(deadline1, deadline2);
let delay = handle.delay(deadline1);
let join = handle.deadline(delay, deadline2);
let join = handle.timeout(delay, deadline2);
exec.push({
join.and_then(move |_| {
+5 -1
View File
@@ -1,9 +1,13 @@
[package]
name = "tokio-tls"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "tokio-tls-0.2.x" git tag.
# - Create "v0.2.x" git tag.
version = "0.2.1"
authors = ["Carl Lerche <[email protected]>"]
license = "MIT"
+1
View File
@@ -1,6 +1,7 @@
[package]
name = "tokio-trace"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+1
View File
@@ -1,6 +1,7 @@
[package]
name = "tokio-trace-core"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+4 -2
View File
@@ -1,10 +1,12 @@
[package]
name = "tokio-udp"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Update doc URL.
# - Create "v0.1.x" git tag.
version = "0.1.3"
authors = ["Carl Lerche <[email protected]>"]
+1
View File
@@ -1,6 +1,7 @@
[package]
name = "tokio-uds"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
+11
View File
@@ -1,6 +1,17 @@
This changelog only applies to the `tokio` crate proper. Each sub crate
maintains its own changelog tracking changes made in each respective sub crate.
# 0.1.20 (May 14, 2019)
### Added
- `tokio::runtime::Builder::panic_handler` allows configuring handling
panics on the runtime (#1055).
# 0.1.19 (April 22, 2019)
### Added
- Re-export `tokio::sync::Mutex` primitive (#964).
# 0.1.18 (March 22, 2019)
### Added
+5 -13
View File
@@ -1,17 +1,18 @@
[package]
name = "tokio"
# When releasing to crates.io:
# - Remove path dependencies
# - Update html_root_url.
# - Update doc url
# - Cargo.toml
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
version = "0.1.19"
version = "0.1.20"
authors = ["Carl Lerche <[email protected]>"]
license = "MIT"
readme = "README.md"
documentation = "https://docs.rs/tokio/0.1.19/tokio/"
documentation = "https://docs.rs/tokio/0.1.20/tokio/"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://tokio.rs"
description = """
@@ -54,12 +55,6 @@ timer = ["tokio-timer"]
udp = ["tokio-udp"]
uds = ["tokio-uds"]
# This feature comes with no promise of stability. Things will
# break with each patch release. Use at your own risk.
async-await-preview = [
"tokio-async-await/async-await-preview",
]
[dependencies]
# Only non-optional dependency...
futures = "0.1.20"
@@ -73,8 +68,8 @@ tokio-fs = { version = "0.1.6", optional = true }
tokio-io = { version = "0.1.6", optional = true }
tokio-executor = { version = "0.1.7", optional = true }
tokio-reactor = { version = "0.1.1", optional = true }
tokio-sync = { version = "0.1.3", optional = true, path = "../tokio-sync" }
tokio-threadpool = { version = "0.1.13", optional = true }
tokio-sync = { version = "0.1.5", optional = true }
tokio-threadpool = { version = "0.1.14", optional = true }
tokio-tcp = { version = "0.1.0", optional = true }
tokio-udp = { version = "0.1.0", optional = true }
tokio-timer = { version = "0.2.8", optional = true }
@@ -83,9 +78,6 @@ tokio-trace-core = { version = "0.1", optional = true }
# Needed until `reactor` is removed from `tokio`.
mio = { version = "0.6.14", optional = true }
# Needed for async/await preview support
tokio-async-await = { version = "0.1.0", optional = true }
[target.'cfg(unix)'.dependencies]
tokio-uds = { version = "0.2.1", optional = true }
+5 -36
View File
@@ -1,48 +1,17 @@
use std::future::Future as StdFuture;
use std::pin::Pin;
use std::task::{Context, Poll};
fn map_ok<T: StdFuture>(future: T) -> impl StdFuture<Output = Result<(), ()>> {
MapOk(future)
}
struct MapOk<T>(T);
impl<T> MapOk<T> {
fn future<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) }
}
}
impl<T: StdFuture> StdFuture for MapOk<T> {
type Output = Result<(), ()>;
fn poll(self: Pin<&mut Self>, context: &mut Context) -> Poll<Self::Output> {
match self.future().poll(context) {
Poll::Ready(_) => Poll::Ready(Ok(())),
Poll::Pending => Poll::Pending,
}
}
}
use tokio_futures::compat;
/// Like `tokio::run`, but takes an `async` block
pub fn run_async<F>(future: F)
where
F: StdFuture<Output = ()> + Send + 'static,
F: std::future::Future<Output = ()> + Send + 'static,
{
use tokio_async_await::compat::backward;
let future = backward::Compat::new(map_ok(future));
::run(future);
::run(compat::infallible_into_01(future));
}
/// Like `tokio::spawn`, but takes an `async` block
pub fn spawn_async<F>(future: F)
where
F: StdFuture<Output = ()> + Send + 'static,
F: std::future::Future<Output = ()> + Send + 'static,
{
use tokio_async_await::compat::backward;
let future = backward::Compat::new(map_ok(future));
::spawn(future);
::spawn(compat::infallible_into_01(future));
}
+1 -19
View File
@@ -1,9 +1,5 @@
#![doc(html_root_url = "https://docs.rs/tokio/0.1.19")]
#![doc(html_root_url = "https://docs.rs/tokio/0.1.20")]
#![deny(missing_docs, warnings, missing_debug_implementations)]
#![cfg_attr(
feature = "async-await-preview",
feature(async_await, await_macro, futures_api,)
)]
//! A runtime for writing reliable, asynchronous, and slim applications.
//!
@@ -108,9 +104,6 @@ extern crate tokio_timer;
#[cfg(feature = "udp")]
extern crate tokio_udp;
#[cfg(feature = "async-await-preview")]
extern crate tokio_async_await;
#[cfg(all(unix, feature = "uds"))]
extern crate tokio_uds;
@@ -142,14 +135,3 @@ if_runtime! {
pub use executor::spawn;
pub use runtime::run;
}
// ===== Experimental async/await support =====
#[cfg(feature = "async-await-preview")]
mod async_await;
#[cfg(feature = "async-await-preview")]
pub use async_await::{run_async, spawn_async};
#[cfg(feature = "async-await-preview")]
pub use tokio_async_await::await;
+1 -1
View File
@@ -21,7 +21,7 @@ pub use futures::{future, stream, task, Async, AsyncSink, Future, IntoFuture, Po
#[cfg(feature = "async-await-preview")]
#[doc(inline)]
pub use tokio_async_await::{
pub use tokio_futures::{
io::{AsyncReadExt, AsyncWriteExt},
sink::SinkExt,
stream::StreamExt as StreamAsyncExt,
@@ -0,0 +1,17 @@
use super::Runtime;
use std::future::Future;
impl Runtime {
/// Like `block_on`, but takes an `async` block
pub fn block_on_async<F>(&mut self, future: F) -> F::Output
where
F: Future,
{
use tokio_futures::compat;
match self.block_on(compat::infallible_into_01(future)) {
Ok(v) => v,
Err(_) => unreachable!(),
}
}
}
+3
View File
@@ -69,6 +69,9 @@
mod builder;
mod runtime;
#[cfg(feature = "async-await-preview")]
mod async_await;
pub use self::builder::Builder;
pub use self::runtime::{Runtime, Handle};
pub use tokio_current_thread::spawn;
@@ -0,0 +1,18 @@
use super::Runtime;
use std::future::Future;
impl Runtime {
/// Like `block_on`, but takes an `async` block
pub fn block_on_async<F>(&mut self, future: F) -> F::Output
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
use tokio_futures::compat;
match self.block_on(compat::infallible_into_01(future)) {
Ok(v) => v,
Err(_) => unreachable!(),
}
}
}
+32
View File
@@ -5,6 +5,7 @@ use reactor::Reactor;
use std::io;
use std::sync::Mutex;
use std::time::Duration;
use std::any::Any;
use num_cpus;
use tokio_reactor;
@@ -101,6 +102,37 @@ impl Builder {
self
}
/// Sets a callback to handle panics in futures.
///
/// The callback is triggered when a panic during a future bubbles up to
/// Tokio. By default Tokio catches these panics, and they will be ignored.
/// The parameter passed to this callback is the same error value returned
/// from `std::panic::catch_unwind()`. To abort the process on panics, use
/// `std::panic::resume_unwind()` in this callback as shown below.
///
/// # Examples
///
/// ```
/// # extern crate tokio;
/// # extern crate futures;
/// # use tokio::runtime;
///
/// # pub fn main() {
/// let mut rt = runtime::Builder::new()
/// .panic_handler(|err| std::panic::resume_unwind(err))
/// .build()
/// .unwrap();
/// # }
/// ```
pub fn panic_handler<F>(&mut self, f: F) -> &mut Self
where
F: Fn(Box<Any + Send>) + Send + Sync + 'static,
{
self.threadpool_builder.panic_handler(f);
self
}
/// Set the maximum number of worker threads for the `Runtime`'s thread pool.
///
/// This must be a number between 1 and 32,768 though it is advised to keep
+3
View File
@@ -2,6 +2,9 @@ mod builder;
mod shutdown;
mod task_executor;
#[cfg(feature = "async-await-preview")]
mod async_await;
pub use self::builder::Builder;
pub use self::shutdown::Shutdown;
pub use self::task_executor::TaskExecutor;