mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-09 00:00:08 +02:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
475dabe96d | ||
|
|
951f2fd910 | ||
|
|
4ef736b9d5 | ||
|
|
219f24cbf1 | ||
|
|
ea282efb2e | ||
|
|
042224d33c | ||
|
|
927eb80ad4 | ||
|
|
6a8934e897 | ||
|
|
0e400af78c | ||
|
|
df702130d6 | ||
|
|
949adbb887 | ||
|
|
b2b796a228 | ||
|
|
abb014efc2 | ||
|
|
e5cf0cc717 |
+2
-2
@@ -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
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
[build]
|
||||
target-dir = "../target"
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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" }
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[build]
|
||||
target-dir = "../../target"
|
||||
@@ -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" }
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
#![doc(hidden)]
|
||||
|
||||
pub mod backward;
|
||||
pub mod forward;
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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]>"]
|
||||
|
||||
@@ -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"] }
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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]>"]
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,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,7 +1,7 @@
|
||||
[package]
|
||||
name = "tokio-tcp"
|
||||
|
||||
# When releasing to crates.io:
|
||||
# - Remove path dependencies
|
||||
# - Update html_root_url.
|
||||
# - Update doc url
|
||||
# - Cargo.toml
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -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"
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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::*;
|
||||
}
|
||||
}
|
||||
@@ -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(), ());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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,6 +1,7 @@
|
||||
[package]
|
||||
name = "tokio-threadpool"
|
||||
# When releasing to crates.io:
|
||||
# - Remove path dependencies
|
||||
# - Update html_root_url.
|
||||
# - Update doc url
|
||||
# - Cargo.toml
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = """
|
||||
|
||||
@@ -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,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.
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 |_| {
|
||||
|
||||
@@ -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,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,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
|
||||
|
||||
@@ -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,6 +1,7 @@
|
||||
[package]
|
||||
name = "tokio-uds"
|
||||
# When releasing to crates.io:
|
||||
# - Remove path dependencies
|
||||
# - Update html_root_url.
|
||||
# - Update doc url
|
||||
# - Cargo.toml
|
||||
|
||||
@@ -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
@@ -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 }
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user