1742 Commits

Author SHA1 Message Date
Jon Gjengset
b70f1ce3c0
rt: enable task state assertions under loom (#2192) 2020-01-29 10:50:52 -08:00
Vitor Enes
64e4bd1b2f docs: minor fixes to TcpStream API docs (#2183) 2020-01-28 14:07:51 -08:00
Tore
8ed209b612 docs: fix stream::pending() example (#2189) 2020-01-28 11:07:29 -08:00
Lucio Franco
4a24c7063b sync: add mpsc benchmark (#2166) 2020-01-27 20:48:35 -08:00
Juan Alvarez
e2230f3392 timer: fix out of bounds error (#2184) 2020-01-27 20:46:52 -08:00
Carl Lerche
00e3c29e48
chore: prepare v0.2.11 release (#2179)
Also bumps:
- tokio-macros: v0.2.4
tokio-macros-0.2.4 tokio-0.2.11
2020-01-27 10:32:07 -08:00
Carl Lerche
bcba4aaa54
docs: write sync mod API docs (#2175)
Fixes #2171
2020-01-27 09:11:12 -08:00
Carl Lerche
71c47fabf4
chore: bump nightly version used in CI (#2178)
This requires fixing a few warnings.
2020-01-26 21:54:14 -08:00
daxpedda
4996e27673 macros: fix skipping generics on #[tokio::main] (#2177)
When using #[tokio::main] on a function with generics, the generics are
skipped. Simply using #vis #sig instead of #vis fn #name(#inputs) #ret
fixes the problem.

Fixes #2176
2020-01-26 09:35:39 -08:00
Carl Lerche
5bf06f2b5a
future: provide try_join! macro (#2169)
Provides a `try_join!` macro that supports concurrently driving multiple
`Result` futures on the same task and await the completion of all the
futures as `Ok` or the **first** `Err` future.
2020-01-24 20:26:55 -08:00
Juan Alvarez
12be90e3ff stream: add StreamExt::timeout() (#2149) 2020-01-24 15:22:56 -08:00
Carl Lerche
0d49e112b2
sync: impl equality traits for oneshot::RecvError (#2168) 2020-01-24 15:10:29 -08:00
Avery Harnish
9eca96aa21 rt: improve "no runtime" panic messages (#2145) 2020-01-24 15:10:11 -08:00
Jon Gjengset
a16c9a5a01 rt: test block_in_place followed by Pending (#2120) 2020-01-24 15:08:30 -08:00
Dominic
f0bfebb7e1 fs: add fs::copy (#2079)
Provides an asynchronous version of `std::fs::copy`.

Closes: #2076
2020-01-24 11:43:26 -08:00
Daniel Fox Franke
968c143acd task: add methods for inspecting JoinErrors (#2051)
Adds `is_cancelled()` and `is_panic()` methods to `JoinError`, as well as
`into_panic()` and `try_into_panic()` methods which, when applicable, returns
the payload of the panic.
2020-01-24 11:23:58 -08:00
wqfish
6fbaac91e0 docs: typo fix in runtime doc (#2167) 2020-01-24 10:56:42 -08:00
David Kellum
e35038ed79 rt: add feature flag for using parking_lot internally (#2164)
`parking_lot` provides synchronization primitives that tend to be
more efficient than the ones in `std`. However, depending on
`parking_lot` pulls in a number of dependencies resulting
in additional compilation time.

Adding *optional* support for `parking_lot` allows the end user
to opt-in when the trade offs make sense for their case.
2020-01-24 10:02:19 -08:00
Oleg Nosov
f9ddb93604 docs: use third form in API docs (#2027) 2020-01-24 09:31:13 -08:00
Carl Lerche
a70f7203a4
macros: add pin! macro (#2163)
Used for stack pinning and based on `pin_mut!` from the pin-util crate.

Pinning is used often when working with stream operators and the select!
macro. Given the small size of `pin!` it makes more sense to include a
version than re-export one from a separate crate or require the user to
depend on `pin-util` themselves.
2020-01-23 14:40:43 -08:00
Carl Lerche
7079bcd609
future: provide join! macro (#2158)
Provides a `join!` macro that supports concurrently driving multiple
futures on the same task and await the completion of all futures.
2020-01-23 13:24:30 -08:00
John-John Tedro
f8714e9901
Don't export select unless macros is enabled (#2161) 2020-01-23 18:40:42 +01:00
Artem Vorotnikov
0545b349e1 stream: add StreamExt::fold() (#2122) 2020-01-23 09:03:10 -08:00
Carl Lerche
8cf98d6946
Provide select! macro (#2152)
Provides a `select!` macro for concurrently waiting on multiple async
expressions. The macro has similar goals and syntax as the one provided
by the `futures` crate, but differs significantly in implementation.

First, this implementation does not require special traits to be
implemented on futures or streams (i.e., no `FuseFuture`). A design goal
is to be able to pass a "plain" async fn result into the select! macro.

Even without `FuseFuture`, this `select!` implementation is able to
handle all cases the `futures::select!` macro can handle. It does this
by supporting pre-poll conditions on branches and result pattern
matching. For pre-conditions, each branch is able to include a condition
that disables the branch if it evaluates to false. This allows the user
to guard futures that have already been polled, preventing double
polling. Pattern matching can be used to disable streams that complete.

A second big difference is the macro is implemented almost entirely as a
declarative macro. The biggest advantage to using this strategy is that
the user will not need to alter the rustc recursion limit except in the
most extreme cases.

The resulting future also tends to be smaller in many cases.
2020-01-22 18:59:22 -08:00
kalcutter
f9ea576cca sync: fix broadcast bugs (#2135)
Make sure the tail mutex is acquired when `condvar` is notified,
otherwise the wakeup may be lost and the sender could be left waiting.
Use `notify_all()` instead of `notify_one()` to ensure that the correct
sender is woken. Finally, only do any of this when there are no more
readers left.

Additionally, calling `send()` is buggy and may cause a panic when
the slot has another pending send.
2020-01-22 13:59:05 -08:00
Kevin Leimkuhler
7f580071f3 net: add ReadHalf::{poll,poll_peak} (#2151)
The `&mut self` requirements for `TcpStream` methods ensure that there are at
most two tasks using the stream--one for reading and one for writing.

`TcpStream::split` allows two separate tasks to hold a reference to a single
`TcpStream`. `TcpStream::{peek,poll_peek}` only poll for read readiness, and
therefore are safe to use with a `ReadHalf`.

Instead of duplicating `TcpStream::poll_peek`, a private method is now used by
both `poll_peek` methods that uses the fact that only a `&TcpStream` is
required.

Closes #2136
2020-01-22 13:22:10 -08:00
Przemysław Bitkowski
5fe2df0fba docs: fix link to website (#2103)
replace website link, because previous one was broken
2020-01-22 11:06:26 -08:00
Carl Lerche
176df2448a
macros: remove unused attributes (#2147) 2020-01-22 10:31:48 -08:00
gliderkite
5bbf976268 Enhance documentation of tokio::task::block_in_place (#2155) 2020-01-22 11:34:09 -05:00
David Barsky
90969420a2
docs: fix incorrectly rendered doc tests; tighten phrasing (#2150) 2020-01-21 21:58:20 -05:00
Carl Lerche
bffbaab30d
chore: prepare v0.2.10 release (#2148) tokio-0.2.10 2020-01-21 13:33:02 -08:00
Koki Kato
a5e774bb38 sync: derive PartialEq for error enums (#2137) 2020-01-21 11:25:44 -08:00
Lucio Franco
0bb17300f7 sync: add std error impl for broadcast errors (#2141) 2020-01-21 11:25:05 -08:00
Lucio Franco
c7719a2d29 io: simplify split check (#2144)
* io: Clean up split check

* fix tests
2020-01-21 11:19:36 -08:00
Carl Lerche
38bff0adda
macros: fix #[tokio::main] without rt-core (#2139)
The Tokio runtime provides a "shell" runtime when `rt-core` is not
available. This shell runtime is enough to support `#[tokio::main`] and
`#[tokio::test].

A previous change disabled these two attr macros when `rt-core` was not
selected. This patch fixes this by re-enabling the `main` and `test`
attr macros without `rt-core` and adds some integration tests to prevent
future regressions.
2020-01-21 10:46:32 -08:00
Markus Westerlind
fbe143b142 fix: Prevent undefined behaviour from malicious AsyncRead impl (#2030)
`AsyncRead` is safe to implement but can be implemented so that it
reports that it read more bytes than it actually did. `poll_read_buf` on
the other head implicitly trusts that the returned length is actually
correct which makes it possible to advance the buffer past what has
actually been initialized.

An alternative fix could be to avoid the panic and instead advance by
`n.min(b.len())`
2020-01-21 10:35:13 -08:00
Carl Lerche
9df805ff54
chore: do not depend on loom on windows (#2146)
Loom currently does not compile on windows due to a
transitive dependency on `generator`. The `generator`
crate builds have started to fail on windows CI. Loom
is not run under windows, however, so removing the
loom dependency on windows is sufficient to fix CI.

Refs: https://github.com/Xudong-Huang/generator-rs/issues/19
2020-01-21 10:15:54 -08:00
Lucio Franco
5d82ac2d1e
readme: Add more related tokio projects (#2128) 2020-01-21 10:00:18 -05:00
Maarten de Vries
5bf78d77ad Add a method to test if split streams come from the same stream. (#1762)
* Add a method to test if split streams come from the same stream.

The exposed stream ID can also be used as key in associative containers.

* Document the fact that split stream IDs can dangle.
2020-01-20 19:50:31 -05:00
Vitor Enes
3176d0a48a io: add BufStream::with_capacity (#2125) 2020-01-20 19:27:34 -05:00
David Kellum
bb6c3839ef Yield now docs (#2129)
* add subsections for the blocking and yielding examples in task mod

* flesh out yield_now rustdoc

* add a must_use for yield_now
2020-01-20 16:51:47 -05:00
Pierre Krieger
1475448bdf runtime: add Handle::try_current (#2118)
* runtime: add Handle::try_current

Makes it possible to get a Handle only if a Runtime has been started, without panicing if that isn't the case

* Use an error instead
2020-01-20 11:09:52 -05:00
Pen Tree
7eb8d447ad tokio-tls: rename echo.rs to tls-echo.rs (#2133) 2020-01-19 15:53:28 -05:00
Pen Tree
1222d81741 tokio-tls: rename echo.rs to tls-echo.rs (#2133) 2020-01-19 15:27:22 -05:00
Lucio Franco
619d730d61
task: Introduce a new pattern for task-local storage (#2126)
This PR introduces a new pattern for task-local storage. It allows for storage
and retrieval of data in an asynchronous context. It does so using a new pattern
based on past experience.

A quick example:

```rust
tokio::task_local! {
  static FOO: u32;
}

FOO.scope(1, async move {
    some_async_fn().await;
    assert_eq!(FOO.get(), 1);
}).await;
```

## Background of task-local storage

The goal for task-local storage is to be able to provide some ambiant context in
an asynchronous context. One primary use case is for distributed tracing style
systems where a request identifier is made available during the context of a
request / response exchange. In a synchronous context, thread-local storage
would be used for this. However, with asynchronous Rust, logic is run in a
"task", which is decoupled from an underlying thread. A task may run on many
threads and many tasks may be multiplexed on a single thread. This hints at the
need for task-local storage.

### Early attempt

Futures 0.1 included a [task-local storage][01] strategy. This was based around
using the "runtime task" (more on this later) as the scope. When a task was
spawned with `tokio::spawn`, a task-local map would be created and assigned
with that task. Any task-local value that was stored would be stored in this
map. Whenever the runtime polled the task, it would set the task context
enabling access to find the value.

There are two main problems with this strategy which ultimetly lead to the
removal of runtime task-local storage:

1) In asynchronous Rust, a "task" is not a clear-cut thing.
2) The implementation did not leverage the significant optimizations that the
compiler provides for thread-local storage.

### What is a "task"?

With synchronous Rust, a "thread" is a clear concept: the construct you get with
`thread::spawn`. With asynchronous Rust, there is no strict definition of a
"task". A task is most commonly the construct you get when calling
`tokio::spawn`. The construct obtained with `tokio::spawn` will be referred to
as the "runtime task". However, it is also possible to multiplex asynchronous
logic within the context of a runtime task. APIs such as
[`task::LocalSet`][local-set] , [`FuturesUnordered`][futures-unordered],
[`select!`][select], and [`join!`][join] provide the ability to embed a mini
scheduler within a single runtime task.

Revisiting the primary use case, setting a request identifier for the duration
of a request response exchange, here is a scenario in which using the "runtime
task" as the scope for task-local storage would fail:

```rust
task_local!(static REQUEST_ID: Cell<u64> = Cell::new(0));

let request1 = get_request().await;
let request2 = get_request().await;

let (response1, response2) = join!{
    async {
        REQUEST_ID.with(|cell| cell.set(request1.identifier()));
        process(request1)
    },
    async {
        REQUEST_ID.with(|cell| cell.set(request2.identifier()));
        process(request2)
    },
 };
```

`join!` multiplexes the execution of both branches on the same runtime task.
Given this, if `REQUEST_ID` is scoped by the runtime task, the request ID would
leak across the request / response exchange processing.

This is not a theoretical problem, but was hit repeatedly in practice. For
example, Hyper's HTTP/2.0 implementation multiplexes many request / response
exchanges on the same runtime task.

### Compiler thread-local optimizations

A second smaller problem with the original task-local storage strategy is that
it required re-implementing "thread-local storage" like constructs but without
being able to get the compiler to help optimize. A discussion of how the
compiler optimizes thread-local storage is out of scope for this PR description,
but suffice to say a task-local storage implementation should be able to
leverage thread-locals as much as possible.

## A new task-local strategy

Introduced in this PR is a new strategy for dealing with task-local storage.
Instead of using the runtime task as the thread-local scope, the proposed
task-local API allows the user to define any arbitrary scope. This solves the
problem of binding task-locals to the runtime task:

```rust
tokio::task_local!(static FOO: u32);

FOO.scope(1, async move {

    some_async_fn().await;
    assert_eq!(FOO.get(), 1);

}).await;
```

The `scope` function establishes a task-local scope for the `FOO` variable. It
takes a value to initialize `FOO` with and an async block. The `FOO` task-local
is then available for the duration of the provided block. `scope` returns a new
future that must then be awaited on.

`tokio::task_local` will define a new thread-local. The future returned from
`scope` will set this thread-local at the start of `poll` and unset it at the
end of `poll`. `FOO.get` is a simple thread-local access with no special logic.

This strategy solves both problems. Task-locals can be scoped at any level and
can leverage thread-local compiler optimizations.

Going back to the previous example:

```rust
task_local! {
  static REQUEST_ID: u64;
}

let request1 = get_request().await;
let request2 = get_request().await;

let (response1, response2) = join!{
    async {
        let identifier = request1.identifier();

        REQUEST_ID.scope(identifier, async {
            process(request1).await
        }).await
    },
    async {
        let identifier = request2.identifier();

        REQUEST_ID.scope(identifier, async {
            process(request2).await
        }).await
    },
 };
```

There is no longer a problem with request identifiers leaking.

## Disadvantages

The primary disadvantage of this strategy is that the "set and forget" pattern
with thread-locals is not possible.

```rust
thread_local! {
  static FOO: Cell<usize> = Cell::new(0);
}

thread::spawn(|| {
    FOO.with(|cell| cell.set(123));

    do_work();
});
```

In this example, `FOO` is set at the start of the thread and automatically
cleared when the thread terminates. While this is nice in some cases, it only
really logically  makes sense because the scope of a "thread" is clear (the
thread).

A similar pattern can be done with the proposed stratgy but would require an
explicit setting of the scope at the root of `tokio::spawn`. Additionally, one
should only do this if the runtime task is the appropriate scope for the
specific task-local variable.

Another disadvantage is that this new method does not support lazy initialization
but requires an explicit `LocalKey::scope` call to set the task-local value. In
this case since task-local's are different from thread-locals it is fine.

[01]: https://docs.rs/futures/0.1.29/futures/task/struct.LocalKey.html
[local-set]: #
[futures-unordered]: https://docs.rs/futures/0.3.1/futures/stream/struct.FuturesUnordered.html
[select]: https://docs.rs/futures/0.3.1/futures/macro.select.html
[join]: https://docs.rs/futures/0.3.1/futures/macro.join.html
2020-01-17 14:42:52 -05:00
Artem Vorotnikov
476bf0084a chore: minor fixes (#2121)
* One more clippy fix, remove special instructions from CI

* Fix Collect description
2020-01-16 10:29:02 -05:00
Artem Vorotnikov
bd8971cd95 chore: clippy fixes (#2110) 2020-01-14 15:12:08 -08:00
Carl Lerche
eb1a8e1792
stream: add StreamExt::collect() (#2109)
Provides an asynchronous equivalent to `Iterator::collect()`. A sealed
`FromStream` trait is added. Stabilization is pending Rust supporting
`async` trait fns.
2020-01-13 14:44:06 -08:00
John-John Tedro
5b091fa3f0 io: Drop AsyncBufRead bound on BufStream impl (#2108)
fixes #2064, #2106
2020-01-13 11:33:24 -08:00
Carl Lerche
7c3f1cb4a3
stream: add StreamExt::chain (#2093)
Asynchronous equivalent to `Iterator::chain`.
2020-01-11 16:33:52 -08:00