1755 Commits

Author SHA1 Message Date
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
Carl Lerche
64d2389911
stream: add stream::once (#2094)
An async equivalent to `iter::once`
2020-01-11 13:52:51 -08:00
Carl Lerche
8471e0a0ee
stream: add empty() and pending() (#2092)
`stream::empty()` is the asynchronous equivalent to
`std::iter::empty()`. `pending()` provides a stream that never becomes
ready.
2020-01-11 12:32:19 -08:00
Carl Lerche
0ba6e9abdb
stream: add StreamExt::merge (#2091)
Provides an equivalent to stream `select()` from futures-rs. `merge`
best describes the operation (vs. `select`). `futures-rs` named the
operation "select" for historical reasons and did not rename it back to
`merge` in 0.3. The operation is most commonly named `merge` else where
as well (e.g. ReactiveX).
2020-01-11 12:31:59 -08:00
Jake Rawsthorne
a939dc48b0 sync: impl From<T> and Default for RwLock (#2089) 2020-01-10 14:22:37 -08:00
Carl Lerche
cfd9b36d89
stream: add StreamExt::fuse (#2085) 2020-01-09 20:51:06 -08:00
Lucio Franco
f5c20cd228 chore: update Tokio discord url (#2086) 2020-01-09 20:41:07 -08:00
Carl Lerche
c7c74a5a76
chore: prepare v0.2.9 release (#2084) tokio-0.2.9 2020-01-09 14:20:46 -08:00
Aljoscha Krettek
b34a849b79 docs: fix runtime creation doc in tokio::runtime (#2073)
With the rt-threaded feature flag we create a threaded scheduler by
default. The documentation had a copy-and-paste error from the section
about the basic scheduler.
2020-01-09 12:44:42 -08:00
Tomasz Miąsko
a7a79f28a8 rt: use release ordering in drop_join_handle_fast (#2044)
Previously acquire operations reading a value written by a successful
CAS in `drop_join_handle_fast` did not synchronize with it. The CAS
wasn't guaranteed to happen before the task deallocation, and so
created a data race between the two.

Use release success ordering to ensure synchronization.
2020-01-09 12:06:11 -08:00
Yoshiya Hinosawa
bd28a7a767 docs: fix typo and issue reference (#2080) 2020-01-09 11:50:48 -08:00
Carl Lerche
275769b5b9
rt: fix shutdown deadlock in threaded scheduler (#2082)
Previously, when the threaded scheduler was in the shutdown process, it
would hold a lock while dropping in-flight tasks. If those tasks
included a drop handler that attempted to wake a second task, the wake
operation would attempt to acquire a lock held by the scheduler. This
results in a deadlock.

Dropping the lock before dropping tasks resolves the problem.

Fixes #2046
2020-01-09 11:49:18 -08:00
Lucio Franco
b70615b299 docs: document feature flags (#2081) 2020-01-09 10:38:53 -08:00
Carl Lerche
6406328176
rt: fix threaded scheduler shutdown deadlock (#2074)
Previously, if an IO event was received during the runtime shutdown
process, it was possible to enter a deadlock. This was due to the
scheduler shutdown logic not expecting tasks to get scheduled once the
worker was in the shutdown process.

This patch fixes the deadlock by checking the queues for new tasks after
each call to park. If a new task is received, it is forcefully shutdown.

Fixes #2061
2020-01-08 21:23:10 -08:00
Jeb Rosen
f28c9f0d17
Fix Seek adapter and AsyncSeek error handling for File
* io: Fix the Seek adapter and add a tested example.

  If the first 'AsyncRead::start_seek' call returns Ready,
  'AsyncRead::poll_complete' will be called.

  Previously, a start_seek that immediately returned 'Ready' would cause
  the Seek adapter to return 'Pending' without registering a Waker.

* fs: Do not return write errors from methods on AsyncSeek.

  Write errors should only be returned on subsequent writes or on flush.

  Also copy the last_write_err assert from 'poll_read' to both
  'start_seek' and 'poll_complete' for consistency.
2020-01-08 19:15:57 -08:00
Alice Ryhl
7ee5542182 doc: fix old notes regarding examples and async/await (#2071) 2020-01-07 15:55:10 -08:00
Carl Lerche
7fb54315f1
macros: fix breaking changes (#2069)
Brings back old macro implementations and updates the version of
tokio-macros that tokio depends on.

Prepares a new release.
tokio-0.2.8
2020-01-07 14:29:44 -08:00
Artem Vorotnikov
ffd4025fce chore: prepare tokio-macros v0.2.2 release (#2068) 2020-01-07 16:44:27 -05:00
Carl Lerche
8bf4696f31
chore: prepare v0.2.7 release (#2065) tokio-0.2.7 2020-01-07 11:40:49 -08:00
Carl Lerche
10398b20c0
docs: minor tweaks to StreamExt API docs (#2066) 2020-01-07 11:40:37 -08:00
Alice Ryhl
780d6f91a0 docs: improve tokio::io API documentation (#2060)
* Links are added where missing and examples are improved.
* Improve `stdin`, `stdout`, and `stderr` documentation by going
  into more details regarding what can go wrong in concurrent
  situations and provide examples for `stdout` and `stderr`.
2020-01-07 09:17:01 -08:00
Carl Lerche
45da5f3510
rt: cleanup runtime::context (#2063)
Tweak context to remove more fns and usage of `Option`. Remove
`ThreadContext` struct as it is reduced to just `Handle`. Avoid passing
around individual driver handles and instead limit to the
`runtime::Handle` struct.
2020-01-07 07:53:40 -08:00
Sean McArthur
855d39f849
Fix basic_scheduler deadlock when waking during drop (#2062) 2020-01-06 15:37:03 -08:00
Eliza Weisman
798e86821f task: add ways to run a LocalSet from within a rt context (#1971)
Currently, the only way to run a `tokio::task::LocalSet` is to call its
`block_on` method with a `&mut Runtime`, like

```rust
let mut rt = tokio::runtime::Runtime::new();
let local = tokio::task::LocalSet::new();
local.block_on(&mut rt, async {
  // whatever...
});
```

Unfortunately, this means that `LocalSet` doesn't work with the 
`#[tokio::main]`  and `#[tokio::test]` macros, since the `main` 
function is _already_ inside of a call to `block_on`.

**Solution**

This branch adds a `LocalSet::run` method, which takes a future and
returns a new future that runs that future on the `LocalSet`. This
is analogous to `LocalSet::block_on`, except that it can be called in
an async context.

Additionally, this branch implements `Future` for `LocalSet`. Awaiting
a `LocalSet` will run all spawned local futures until they complete.
This allows code like

```rust
#[tokio::main] 
async fn main() {
    let local = tokio::task::LocalSet::new();

    local.spawn_local(async {
        // ...
    });

    local.spawn_local(async {
        // ...
        tokio::task::spawn_local(...);
        // ...
    });

    local.await;
}
```

The `LocalSet` docs have been updated to show the usage with 
`#[tokio::main]` rather than with manually created runtimes, where
applicable.

Closes #1906 
Closes #1908 
Fixes #2057
2020-01-06 14:44:30 -08:00
Benjamin Fry
0193df3a59 rt: add a Handle::current() (#2040)
Adds `Handle::current()` for accessing a handle to the runtime
associated with the current thread. This handle can then be
passed to other threads in order to spawn or perform other
runtime related tasks.
2020-01-06 11:32:21 -08:00
Tomasz Miąsko
5930acef73 rt: share vtable between waker and waker ref (#2045)
The `Waker::will_wake` compares both a data pointer and a vtable to
decide if wakers are equivalent. To avoid false negatives during
comparison, use the same vtable for a waker stored in `WakerRef`.
2020-01-06 10:39:48 -08:00
Artem Vorotnikov
3540c5b9ee stream: Add StreamExt::any (#2034) 2020-01-06 10:26:53 -08:00
Ivan Petkov
188fc6e0d2 process: deprecate Child stdio accessors in favor of pub fields (#2014)
Fixes #2009
2020-01-06 10:24:40 -08:00
Stepan Koltsov
d45f61c183 doc: document from_std functions panic (#2056)
Document that conversion from `std` types must be done from within
the Tokio runtime context.
2020-01-06 10:06:39 -08:00
Linus Färnstrand
dcfa895b51 chore: use just std instead of ::std in paths (#2049) 2020-01-06 10:04:21 -08:00
Carl Lerche
f0006006ed
time: advance frozen time in park_timeout (#2059)
This patch improves the behavior of frozen time (a testing utility made
available with the `test-util` feature flag). Instead of of requiring
`time::advance` to be called in order to advance the value returned by
`Instant::now`, calls to `time::Driver::park_timeout` will use the
provided duration to advance the time.

This is the desired behavior as the timeout is used to indicate when the
next scheduled delay needs to be fired.
2020-01-06 08:47:34 -08:00
John Van Enk
84ff73e687 tokio: remove documentation stating Receiver is clone-able. (#2037)
* tokio: remove documentation stating `Receiver` is clone-able.

The documentation for `broadcast` stated that both `Sender` and
`Receiver` are clonable. This isn't the case: `Receiver`s cannot be
cloned (and shouldn't be cloned).

In addition, mention that `Receiver` is `Sync`, and mention that both
`Receiver` and `Sender` are `Send`.

Fixes: #2032

* Clarify that Sender and Receiver are only Send and Sync if T is Send or Sync.
2020-01-06 11:28:26 -05:00
João Oliveira
32e15b3a24 sync: add RwLock (#1699)
Provides a `RwLock` based on a semaphore. The semaphore is initialized
with 32 permits. A read acquires a single permit and a write acquires all 32
permits. This ensures that reads (up to 32) may happen concurrently and
writes happen exclusively.
2020-01-03 21:03:26 -08:00
Carl Lerche
efcbf9613f
sync: add batch op support to internal semaphore (#2004)
Extend internal semaphore to support batch operations. With this PR,
consumers of the semaphore are able to atomically request more than one
permit. This is useful for implementing a RwLock.
2020-01-03 10:34:15 -08:00
Artem Vorotnikov
3736467dbb stream: correct trait bounds for all (#2043) 2020-01-02 15:03:53 -08:00
Artem Vorotnikov
e43f28f6a8 macros: do not automatically pull rt-core (#2038) 2020-01-02 11:22:15 -08:00
Artem Vorotnikov
3cf91db4b6 stream: add StreamExt::all (#2035) 2020-01-02 11:36:38 -05:00
Artem Vorotnikov
e8fcf55881 Refactor proc macros, add more knobs (#2022)
* Refactor proc macros, add more knobs

* make macros work with rt-core
2019-12-27 13:56:43 -05:00