Compare commits

...
751 Commits
Author SHA1 Message Date
Carl Lerche 2e62374e4a rt: pad the task struct to avoid false sharing (#5809)
This change pads the task struct to avoid false sharing. It is possible
for these structs to overlap cache lines without this alignment.
2023-06-21 09:39:14 -07:00
Jack Wrenn 56c4365584 tokio: improve taskdump documentation (#5805)
- Add example trace output.
- Add note on enabling unstable features.
- Add note on performance overhead.
2023-06-19 13:34:48 -04:00
Andrew Mackenzie fb0d305a7a ci: build tokio for redox-os (#5800) 2023-06-19 19:33:17 +02:00
盏一 848482d2bb rt(threaded): adjust transition_from_parked behavior after introducing disable_lifo_slot feature (#5753) 2023-06-14 12:42:31 +02:00
Andrew Mackenzie 00af6eff77 net: add support for Redox OS (#5790) 2023-06-13 12:42:40 +02:00
icedrocket b7290910f7 sync: fix typo in batch semaphore (#5789) 2023-06-12 15:43:12 +02:00
Taiki Endo af6c87a045 chore: upgrade remaining 2018 edition crates to 2021 edition (#5788) 2023-06-12 02:21:50 +09:00
Taiki Endo 6257712d68 ci: update cargo-check-external-types to 0.1.7 (#5786) 2023-06-11 19:02:12 +09:00
Taiki Endo c5d52c17ae chore: enable cargo v2 resolver to prevent dev-deps from enabling log feature of mio (#5787) 2023-06-11 17:34:22 +09:00
Erk 2a54ad01d0 time: do not overflow to signal value (#5710) 2023-06-10 14:24:19 +02:00
Jack Wrenn cb18b0a231 tokio: improve task dump documentation (#5778)
Adds depth to the taskdump example, and documentation to Handle::dump.
2023-06-10 13:30:08 +02:00
nvartolomei 7ccd3e0c6d task: add JoinSet::poll_join_next (#5721) 2023-06-10 13:19:07 +02:00
Bugen Zhao e63d0f10bf task: use pin-project for TaskLocalFuture (#5758)
Signed-off-by: Bugen Zhao <[email protected]>
2023-06-10 12:38:52 +02:00
Alice Ryhl a2941e48be ci: temporarily disable semver check (#5774) 2023-06-08 10:36:25 +02:00
Carl Lerche 1c8d22c18b rt: reduce code defined in macros (#5773)
Instead of defining code in macros, move code definition to sub modules
and use the cfg_macro to declare the module.
2023-06-07 08:48:27 -07:00
Carl Lerche cbb3c155dd rt: panic if EnterGuard dropped incorrect order (#5772)
Calling `Handle::enter()` returns a `EnterGuard` value, which resets the
thread-local context on drop. The drop implementation assumes that
guards from nested `enter()` calls are dropped in reverse order.
However, there is no static enforcement of this requirement.

This patch checks that the guards are dropped in reverse order and
panics otherwise. A future PR will deprecate `Handle::enter()` in favor
of a method that takes a closure, ensuring the guard is dropped
appropriately.
2023-06-07 08:47:58 -07:00
Jack Wrenn 038c4d9999 rt: implement task dumps for multi-thread runtime (#5717)
This patch implements task dumps on the multi-thread runtime. It
complements #5608, which implemented task dumps on the current-thread
runtime.
2023-06-06 13:55:37 -07:00
Folkert de Vries 7b24b22901 io: support PRIORITY epoll events (#5566)
Add support for epoll priority events. The commit adds `Interest::PRIORITY`, `ready`, and `ready_mut` functions to `AsyncFd`.

Closes #4885
2023-06-06 11:57:20 -07:00
Carl Lerche 779b9c19d5 ci: disable tuning test when runing ASAN (#5770)
The tuning test relies on a predictable execution environment. It
assumes that spawning a new task can complete reasonably fast. When
running tests with ASAN, the tuning test will spurriously fail. After
investigating, I believe this is due to running tests with ASAN enabled
and without `release` in a low resource environment (CI) results in an
execution environment that is too slow for the tuning test to succeed.
2023-06-06 09:35:19 -07:00
Carl Lerche 1204da7300 rt: split runtime::context into multiple files (#5768)
This PR restructures `runtime::context` into multiple files by component and feature flag. The goal is to reduce code defined in macros and make each context component more manageable.

There should be no behavior changes except tweaking how the RNG seed is set. Instead of putting it in `set_current`, we set it when entering the runtime. This aligns better with the feature's original intent, enabling users to make a runtime's RNG deterministic. The seed should not be changed by `Handle::enter()`, so there is no need to have the code in `context::set_current`.
2023-06-06 08:37:11 -07:00
Carl Lerche e75ca93d30 rt: EnterGuard should not be Send (#5766)
Removes `Send` from `EnterGuard` (returned by `Handle::enter()`. The
guard type changes a thread-local variable on drop. If the guard is
moved to a different thread, it would modify the wrong thread-local.

This is a **breaking change** but it fixes a bug and prevents incorrect
user behavior. If user code breaks because of this, it is because they
(most likely) have a bug in their code.
2023-06-05 14:09:43 -07:00
Alice Ryhl 15712018da rt: Scoped should not be Sync (#5765)
If the `Scoped` type is `Sync`, then you can call `set` from two threads in parallel. Since it accesses `inner` without synchronization, this is a data race.

This is a soundness issue for the `Scoped` type, but since this is an internal API and we don't use it incorrectly anywhere, no harm is done.
2023-06-05 09:36:48 -07:00
icedrocket 076d77c186 macros: fix diagnostics of last statement (#5762) 2023-06-04 15:10:59 +02:00
John-John Tedro e2853c1b49 rt: remove dead platform.rs file (#5761) 2023-06-04 13:20:38 +02:00
Carl Lerche 8f0103f6c5 rt: make CONTEXT const TLS (#5757)
This makes initializing `Context` const, which lets us use const
thread-locals. The next step will be to ensure `Context` does not have a
drop impl.
2023-06-03 14:16:45 -07:00
Carl Lerche fb4d43017d rt(threaded): move inject queue lock to worker (#5754)
This commit is a step towards the ongoing effort to unify the mutex in
the multi-threaded scheduler. The Inject queue is split into two
structs. `Shared` holds fields that are concurrently accessed, and
`Synced` holds fields that must be locked to access. The multi-threaded
scheduler is responsible for locking `Synced` and passing it in when
needed.

The commit also splits `inject` into multiple files to help reduce the
amount of code defined in macros.
2023-06-02 13:36:06 -07:00
Carl Lerche 1e14ef0093 ci: fix spurious CI failure (#5752)
PR #5720 introduced runtime self-tuning. It included a test that
attempts to verify self-tuning logic. The test is heavily reliant on
timing details. This patch attempts to make the test a bit more reliable
by not assuming tuning will converge within a set amount of time.
2023-06-01 17:15:48 -07:00
Carl Lerche a8b6353535 rt: move Inject to runtime::scheduler (#5748)
Previously, `Inject` was defined in `runtime::task`. This was because it
used some internal fns as part of the intrusive linked-list
implementation.

In the future, we want to remove the mutex from Inject and move it to
the scheduler proper (to reduce mutex ops). To set this up, this commit
moves `Inject` to `runtime::scheduler`. To make this work, we have to
`pub(crate)` `task::RawTask` and use that as the interface to access the
next / previous pointers.
2023-06-01 14:56:12 -07:00
Carl Lerche c748f4965e rt: move deferred task list to scheduler (#5741)
Previously, the deferred task list (list of tasks that yielded and are
waiting to be woken) was stored on the global runtime context. Because
the scheduler is responsible for waking these tasks, it took additional
TLS reads to perform the wake operation.

Instead, this commit moves the list of deferred tasks into the scheduler
context. This makes it easily accessible from the scheduler itself.
2023-06-01 11:36:28 -07:00
Carl Lerche a96dab1089 rt: start work to unify MT scheduler mutexes (#5747)
In order to reduce the number of mutex operations in the multi-threaded
scheduler hot path, we need to unify the various mutexes into a single
one. To start this work, this commit splits up `Idle` into `Idle` and
`Synced`. The `Synced` component is stored separately in the scheduler's
`Shared` structure.
2023-06-01 09:17:43 -07:00
Carl Lerche 79a7e78c0d rt(threaded): basic self-tuning of injection queue (#5720)
Each multi-threaded runtime worker prioritizes pulling tasks off of its
local queue. Every so often, it checks the injection (global) queue for
work submitted there. Previously, "every so often," was a constant
"number of tasks polled" value. Tokio sets a default of 61, but allows
users to configure this value.

If workers are under load with tasks that are slow to poll, the
injection queue can be starved. To prevent starvation in this case, this
commit implements some basic self-tuning. The multi-threaded scheduler
tracks the mean task poll time using an exponentially-weighted moving
average. It then uses this value to pick an interval at which to check
the injection queue.

This commit is a first pass at adding self-tuning to the scheduler.
There are other values in the scheduler that could benefit from
self-tuning (e.g. the maintenance interval). Additionally, the
current-thread scheduler could also benfit from self-tuning. However, we
have reached the point where we should start investigating ways to unify
logic in both schedulers. Adding self-tuning to the current-thread
scheduler will be punted until after this unification.
2023-06-01 08:13:24 -07:00
Chris Constantine 7c12e41d07 io: add AsyncRead/AsyncWrite passthrough for Inspect (#5739) 2023-06-01 15:35:03 +02:00
Alice Ryhl 7a99f87df2 taskdump: instrument the remaining leaf futures (#5708) 2023-05-31 18:27:40 +02:00
RaccoonSupremacy 0b2c9b8bab util: add reexport of bytes crate (#5725) 2023-05-28 19:12:40 +02:00
Carl Lerche 98c8c38e96 ci: speed up multi-threaded runtime loom tests. (#5723)
Increase max preemption back to 2 while running the tests in under 90 minutes.
2023-05-27 16:34:59 -07:00
Alice Ryhl 080d52902f Merge 'tokio-1.28.2' into 'master' (#5737) 2023-05-27 20:39:03 +02:00
Alice Ryhl e87ff8a83a chore: prepare Tokio v1.28.2 (#5736) 2023-05-27 20:38:02 +02:00
Alice Ryhl 1605279abf Merge 'tokio-1.25.1' into 'tokio-1.28.x' (#5735) 2023-05-27 20:36:34 +02:00
Alice Ryhl 25258d572a chore: prepare Tokio v1.25.1 (#5734) 2023-05-27 20:32:20 +02:00
Alice Ryhl 8ddb58bf6c Merge 'tokio-1.20.5' into 'tokio-1.25.x' (#5733) 2023-05-27 20:30:39 +02:00
Alice Ryhl 4b032a25a4 ci: use a fixed stable on 1.25.x (#5732)
This cherry-picks:
 * chore: remove ntapi dev-dependency
 * time: fix repeatedly_reset_entry_inserted_as_expired test
2023-05-27 17:20:38 +02:00
Alice Ryhl edd172cd32 chore: prepare Tokio v1.20.5 (#5731) 2023-05-27 15:41:02 +02:00
Alice Ryhl 9877fa2a97 Merge 'tokio-1.18.6' into 'tokio-1.20.x' (#5730) 2023-05-27 15:29:59 +02:00
Alice Ryhl 0f898a3148 chore: prepare Tokio v1.18.6 (#5729) 2023-05-27 15:26:45 +02:00
Alice Ryhl d6a9ef5333 tokio: disable default features for mio (#5728) 2023-05-27 15:18:15 +02:00
Alice Ryhl 2a180188c6 ci: fix CI for 1.18.x branch (#5728)
Some of these changes will be progressively reverted as we merge this
into newer branches.
2023-05-27 15:05:34 +02:00
Carl Lerche 9f9db7da63 rt: move scheduler ctxs to runtime::context (#5727)
This commit eliminates the current_thread::CURRENT and multi_thread::current
thread-local variables in favor of using `runtime::context`. This is another step
towards reducing the total number of thread-local variables used by Tokio.
2023-05-26 19:07:20 -07:00
Carl Lerche d274ef3748 rt: avoid cloning runtime::Handle in spawn (#5724)
This commit updates `tokio::spawn` to avoid having to clone
`runtime::Handle`.
2023-05-26 08:08:53 -07:00
Nano 5e6d4c7999 task: typo fix (#5726) 2023-05-26 15:43:04 +02:00
Carl Lerche 9eb3f5b556 rt(threaded): cap LIFO slot polls (#5712)
As an optimization to improve locality, the multi-threaded scheduler
maintains a single slot (LIFO slot). When a task is scheduled, it goes
into the LIFO slot. The scheduler will run tasks in the LIFO slot first
before checking the local queue.

Ping-ping style workloads where task A notifies task B, which
notifies task A again, can cause starvation as these two tasks 
repeatedly schedule the other in the LIFO slot. #5686, a first
attempt at solving this problem, consumes a unit of budget each time a
task is scheduled from the LIFO slot. However, at the time of this
commit, the scheduler allocates 128 units of budget for each chunk of
work. This is relatively high in situations where tasks do not perform many
async operations yet have meaningful poll times (even 5-10 microsecond
poll times can have an outsized impact on the scheduler).

In an ideal world, the scheduler would adapt to the workload it is
executing. However, as a stopgap, this commit limits the times
the LIFO slot is prioritized per scheduler tick.
2023-05-23 14:38:15 -07:00
Carl Lerche 3a94eb0893 rt: batch pop from injection queue when idle (#5705)
In the multi-threaded scheduler, when there are no tasks on the local
queue, a worker will attempt to pull tasks from the injection queue.
Previously, the worker would only attempt to poll one task from the
injection queue then continue trying to find work from other sources.
This can result in the injection queue backing up when there are many
tasks being scheduled from outside of the runtime.

This patch updates the worker to try to poll more than one task from the
injection queue when it has no more local work. Note that we also don't
want a single worker to poll **all** tasks on the injection queue as
that would result in work becoming unbalanced.
2023-05-23 08:16:41 -07:00
Carl Lerche 93bde0870f rt: use task::Inject with current_thread scheduler (#5702)
Previously, the current_thread scheduler used its own injection queue
instead of sharing the same one as the multi-threaded scheduler. This
patch updates the current_thread scheduler to use the same injection
queue as the multi-threaded one (`task::Inject`).

`task::Inject` includes an optimization where it does not need to
acquire the mutex if the queue is empty.
2023-05-21 00:08:00 +00:00
Carl Lerche ddd7250e62 ci: update nightly version (#5706) 2023-05-20 11:00:50 +02:00
Carl Lerche f64a1a3dbd chore: rm .cargo/config and include in .gitignore (#5707)
It was most likely included by accident.
2023-05-19 19:21:47 -07:00
Carl Lerche c88f9bc930 rt: small current_thread scheduler cleanup (#5701)
There should be no functional changes.
2023-05-19 08:15:31 -07:00
Joris Kleiber 29a6f468a6 process: add raw_arg method to Command (#5704) 2023-05-19 15:42:38 +02:00
Carl Lerche 8c076cb00d rt: add internal counters to threaded runtime. (#5700)
These counters are enabled using the `tokio_internal_mt_counters` and
are intended to help with debugging performance issues.

Whenever I work on the threaded runtime, I often find myself adding
these counters, then removing them before submitting a PR. I think
keeping them in will save time in the long run and shouldn't impact dev
much.
2023-05-18 20:28:47 +00:00
Carl Lerche c84d0a14b1 rt: instrument task poll times with a histogram (#5685)
Adds support for instrumenting the poll times of all spawned tasks. Data is tracked in a histogram. The user must specify the histogram scale and bucket ranges. Implementation-wise, the same strategy is used in the runtime where we are just using atomic counters. Because instrumenting each poll duration will result in frequent calls to `Instant::now()`, I think it should be an opt-in metric.
2023-05-15 15:20:41 -07:00
Alex Robinson a883fd4378 docs: link to latest version of tokio-util docs (#5694) 2023-05-15 21:07:08 +02:00
Carl Lerche 1014262d34 ci: skip miri tests when running loom (#5695)
Disables a recently added miri test when running loom tests.
2023-05-15 11:11:56 -07:00
Alice Ryhl f6313f4382 task: fix stacked borrows issue in JoinSet (#5693) 2023-05-15 17:55:52 +02:00
Alice Ryhl 70364b7079 runtime: fix possible starvation when using lifo slot (#5686) 2023-05-15 12:40:04 +00:00
Marek Kuskowski dd9471d13a sync: add broadcast::Receiver::blocking_recv (#5690) 2023-05-15 14:01:18 +02:00
Alice Ryhl 4e2ef63c4e ci: only check fuzz tests after basic tests (#5687) 2023-05-14 12:43:37 +02:00
Hootan Shadmehr dec390df1e ci: check that tokio-stream/fuzz compiles (#5682) 2023-05-10 20:17:50 +02:00
Alice Ryhl 89b73f39bf Merge 'tokio-1.28.x' into 'master' (#5680) 2023-05-10 10:46:39 +02:00
Alice Ryhl a26fc9c9f9 chore: prepare Tokio v1.28.1 (#5679) 2023-05-10 10:44:04 +02:00
Hootan Shadmehr 7fe88ce4ad fuzz: remove unused code from fuzz_steam_map.rs (#5675) 2023-05-10 10:04:36 +02:00
Dirkjan Ochtman f2d033e454 build: fix warnings in AS_FD_PROBE (#5677) 2023-05-09 21:57:35 +02:00
Daniel Bloom c999699f5e sync: remove 'static bound from PollSender (#5665) 2023-05-09 16:01:57 +00:00
Alice Ryhl 7430865d65 taskdump: instrument JoinHandle and tokio::fs (#5676) 2023-05-09 10:14:59 +00:00
Vidhan Bhatt 56239a9035 macros: fix typo in doc comment (#5671) 2023-05-08 17:50:49 +02:00
Matilda Smeds 1b4106a1ce net: add nodelay methods on TcpSocket (#5672) 2023-05-06 14:35:20 +02:00
Hootan Shadmehr 3abe877bf7 ci: check that tokio/fuzz compiles (#5670) 2023-05-03 22:00:06 +02:00
Gil Shoshan 61b68a8abc sync: implement more traits for channel errors (#5666) 2023-05-03 09:59:07 +02:00
icedrocket 52bc6b6f2d fs: reduce blocking ops in fs::read_dir (#5653) 2023-04-28 11:38:38 +02:00
Jack Wrenn f478ff4a24 tokio: add CountedLinkedList::for_each (#5660) 2023-04-27 22:24:44 +02:00
Jack Wrenn 660eac71f0 taskdump: implement task dumps for current-thread runtime (#5608)
Task dumps are snapshots of runtime state. Taskdumps are collected by
instrumenting Tokio's leaves to conditionally collect backtraces, which
are then coalesced per-task into execution tree traces.

This initial implementation only supports collecting taskdumps from
within the context of a current-thread runtime, and only `yield_now()`
is instrumented.
2023-04-27 12:59:20 +02:00
Matilda Smeds 1d785fd66f metrics: add metric for number of tasks (#5628) 2023-04-27 12:58:31 +02:00
Alice Ryhl 6a8f6f5a90 net: add uds doc alias for unix sockets (#5659) 2023-04-26 12:12:53 +02:00
Alice Ryhl 398dfda56d chore: prepare tokio-stream v0.1.14 (#5658) 2023-04-26 10:47:43 +02:00
Alice Ryhl 9bdc475539 stream: fix minimum Tokio dependency (#5657) 2023-04-26 10:13:35 +02:00
Alice Ryhl b5a5ddb4cf chore: prepare tokio-stream v0.1.13 (#5652) 2023-04-25 20:21:32 +02:00
Alice Ryhl 74c6e6c683 chore: prepare tokio-util v0.7.8 (#5651) 2023-04-25 20:21:20 +02:00
Alice Ryhl f21d596099 chore: prepare Tokio v1.28.0 (#5650) 2023-04-25 20:21:00 +02:00
Alice Ryhl 66c62a4b74 chore: prepare tokio-macros v2.1.0 (#5649) 2023-04-25 17:07:08 +02:00
Predrag Gruevski a86c052218 ci: use cargo-semver-checks GitHub Action (#5648) 2023-04-25 00:17:17 +02:00
Debadree Chatterjee c1778eda38 sync: add watch::Receiver::wait_for (#5611) 2023-04-24 15:48:07 +02:00
Fergus Mitchell 11b8807544 sync: improve Debug impl for RwLock (#5647) 2023-04-24 15:39:42 +02:00
jrray e789b61424 stream: add StreamExt::timeout_repeating (#5577) 2023-04-24 09:27:24 +02:00
Burkhard Mittelbach 2cd4f4ab46 stream: add "full" feature flag (#5639) 2023-04-23 13:59:49 +02:00
Taiki Endo b6bbe5f487 Revert "macros: hide internal constant in select! macro (#5617)" (#5637)
This reverts commit cf9a03c107.
2023-04-23 20:38:50 +09:00
Denis Kayshev 57ba4a4b10 sync: fix typo in Semaphore::MAX_PERMITS (#5645) 2023-04-22 18:52:07 +02:00
Alice Ryhl 5e6c6bdafd chore: fix compiler output changes in rustc 1.69 (#5643) 2023-04-21 07:10:55 +00:00
Alice Ryhl 77e3911806 chore: remove ntapi dev-dependency (#5642) 2023-04-21 08:38:46 +02:00
Alice Ryhl b9868b23aa rt: fix spurious yield_defers_until_park test (#5634) 2023-04-20 18:00:33 +02:00
Adam Chalmers 623483c81f docs: fix typo in #[tokio::test] docs (#5636)
Both current- and multi-thread runtime claimed to be the default, but only current thread actually is.
2023-04-20 14:12:43 +00:00
Sigurd 5cef6eba7b sync: improve CancellationToken doc on child tokens (#5632) 2023-04-19 17:42:32 +02:00
Tymoteusz Wiśniewski db543639e1 sync: reduce contention in Notify (#5503) 2023-04-19 13:07:10 +02:00
isabelleatkins 9f9e596eec time: fix panic in DelayQueue (#5630) 2023-04-17 20:51:42 +00:00
Jake Goulding f6cb6e084b task: add JoinSet::spawn_blocking (#5612) 2023-04-17 08:20:27 +00:00
Timmy Xiao 7aea597a8f io: make read_to_end not grow unnecessarily (#5610) 2023-04-16 20:23:53 +02:00
Aviram Hassan 9507f8b374 stream: add StreamNotifyClose (#4851) 2023-04-16 15:04:00 +00:00
Folkert de Vries 6037faeede io: add AsyncFd::async_io (#5542) 2023-04-16 16:27:58 +02:00
Tymoteusz Wiśniewski 8497f379b5 sync: avoid deadlocks in broadcast with custom wakers (#5578) 2023-04-16 16:22:38 +02:00
Hayden Stainsby 1b22cbfd33 readme: update clippy version in contrib guide (#5623)
In CI, we are using a newer version of Clippy than what is stated in the
contributions guide.

Additionally, it is no longer necessary to use Clippy from the MSRV. As
of Clippy 1.64, the `rust-version` field in Cargo.toml is respected.

The text and the command have been updated to reflect the current state
of CI and best practices.
2023-04-16 15:46:01 +02:00
Jens Reidel effead29d1 time: add DelayQueue::peek (#5569)
Signed-off-by: Jens Reidel <[email protected]>
2023-04-16 09:43:03 +02:00
Alexander van Ratingen 3b16564ce0 sync: add OwnedSemaphorePermit::semaphore (#5618) 2023-04-15 20:55:39 +02:00
John-John Tedro fc1e03f91b macros: make entrypoints more efficient (#5621) 2023-04-15 20:55:00 +02:00
John-John Tedro ea5d448ee8 ci: gate costly checks behind basic ones (#5622) 2023-04-15 20:16:42 +02:00
Iron(III) Oxide abc93f615e fuzz: fix fuzz warnings (#5614) 2023-04-13 16:07:12 +02:00
mTsBucy1 cf9a03c107 macros: hide internal constant in select! macro (#5617) 2023-04-12 21:32:38 +09:00
Alice Ryhl 3b45e8614d stream: update StreamMap fuzz test (#5600)
This fuzz test touches some quadratic time code paths. This changes the
test to limit the test size so that the test doesn't time out.
2023-04-11 10:40:10 +02:00
Alice Ryhl b02c550c52 ci: fix FreeBSD ci (#5613) 2023-04-10 15:26:59 +02:00
Oddbjørn Grødem 03912b9cf7 sync: add same_channel to broadcast channel (#5607) 2023-04-07 14:18:47 +02:00
Daniel Sedlak d4afbad6e5 tokio: fix typos (#5604) 2023-04-06 14:29:12 +02:00
Daniel Netzer b1ca0d8b12 ci: fix typo in ci.yml (#5599) 2023-04-05 09:35:47 +00:00
Iron(III) Oxide 16cdb109f4 io: impl BufMut for ReadBuf (#5590) 2023-04-04 22:00:41 +02:00
Taiki Endo 88445e762c deps: update windows-sys to 0.48 (#5591) 2023-04-02 09:31:27 +02:00
teor 3c403d6ee8 coop: fix typo in poll_proceed() doc comment (#5589) 2023-03-30 13:25:05 +02:00
Dmitry Rodionov d63d659078 sync: fix typo in tokio::sync::watch::Sender docs (#5587) 2023-03-29 18:05:24 +00:00
Flavio Bizzarri b31f1a4662 net: add recv_buf for UdpSocket and UnixDatagram (#5583) 2023-03-28 18:17:22 +00:00
Qiu Chaofan 663e56e983 net: support AIX get_peer_cred (#5065) 2023-03-28 11:25:12 +02:00
Alice Ryhl 1df874ead4 chore: prepare Tokio v1.27.0 (#5584) 2023-03-27 23:55:48 +02:00
Alice Ryhl 614fe357fc chore: prepare tokio-macros v2.0.0 (#5580) 2023-03-27 22:45:54 +02:00
sgasseandSimon B. Gasse 68b02db154 time: fix wake-up with interval on Ready (#5553)
When `tokio::time::Interval::poll_tick()` returns `Poll::Pending`, it
schedules itself for being woken up again through the waker of the
passed context, which is correct behavior.

However when `Poll::Ready(_)` is returned, the interval timer should be
reset but not scheduled to be woken up again as this is up to the
caller.

This commit fixes the bug by introducing a `reset_without_reregister`
method on `TimerEntry` which is called by `Intervall::poll_tick(cx)` in
case the delay poll returns `Poll::Ready(_)`.

Co-authored-by: Simon B. Gasse <[email protected]>
2023-03-27 17:39:53 +02:00
Alice Ryhl 822af18cf5 sync: fix Semaphore::MAX_PERMITS test (#5582) 2023-03-25 18:09:05 +00:00
David Pedersen 92d33b7181 macros: update syn (#5572) 2023-03-23 23:38:59 +01:00
Marcelo Diop-Gonzalez 1cb7bf11b3 time: clean up redundant check in Wheel::poll() (#5574)
The condition checked in the and_then() call is the same as is checked
in the match below, so we can clean it up by just matching on
next_expiration() directly.
2023-03-23 09:53:54 -07:00
João Marcos 768ede65c1 io: refer to ReaderStream and StreamReader in module docs (#5576) 2023-03-23 15:31:40 +00:00
João Marcos 54a394696f io: add details to docs of tokio::io::copy[_buf] (#5575) 2023-03-23 15:19:51 +00:00
Hayden Stainsby 35dd635630 tracing: fix spawn_blocking location fields (#5573)
In a previous PR (#4128), the `spawn.location` field on task spans was
structured into 3 separate fields for the `file`, `line`, and `col`.
There is a separately created span for blocking tasks which was missed.

This caused tasks created with `spawn_blocking` to appear in
`tokio-console` without a location, but with an additional "free form"
field containing the formatted source code location.

This change modifies this span to use the same format. The span creation
needs to be separate from the other task spans because it records the
function name. This information is useful in the `spawn_blocking` case,
but can be "catastrophically long" in the `async fn` case and was
removed in #3074.
2023-03-22 22:08:01 +01:00
Timmy Xiao a7bb054414 tokio: update stream, util, test to 2021 edition (#5571) 2023-03-21 17:36:40 +00:00
Alice Ryhl 0c8e8248f8 tokio: bump MSRV to 1.56 (#5559) 2023-03-21 18:06:47 +01:00
Alice Ryhl 2dfe4e8885 time: fix repeatedly_reset_entry_inserted_as_expired test (#5570) 2023-03-21 18:06:22 +01:00
Alice Ryhl b489acb46c sync: try to lock the parent first in CancellationToken (#5561) 2023-03-21 14:20:33 +01:00
Ivan Zderadicka d46c844bb9 examples: fix panic in tinyhttp example (#5328)
As method in httparse result is no longer part of input buffer it needs
to be handled separately.
2023-03-20 18:52:38 +01:00
devensiv 4cd4b02389 io: fix wait operation on mock (#5554) 2023-03-19 12:35:39 +00:00
daxpedda 17cc283f58 macros: accept path as crate rename (#5557) 2023-03-19 12:28:43 +01:00
Alice Ryhl 0a93ed7e7a io: use memchr from libc (#5558) 2023-03-19 10:49:19 +00:00
Alice Ryhl cef98e25e7 macros: define cancellation safety (#5525) 2023-03-18 21:25:23 +00:00
Tymoteusz Wiśniewski e7bd754231 fs: fuse std iterator in ReadDir (#5555)
Implementation of Tokio's ReadDir assumes that ReadDir from std is
fused, but that's not the case on Windows. This change wraps the std
iterator in std::iter::Fuse to make its usage correct.
2023-03-18 14:07:40 +01:00
Austin Bonander d459a93453 net: add UdpSocket::peek_sender() (#5520) 2023-03-17 10:22:42 +01:00
Shaye Garg f177aad6e4 task: add JoinHandle::abort_handle (#5543) 2023-03-16 14:02:48 +01:00
Tymoteusz Wiśniewski 4ea632005d tokio: make all windows docs visible in unix builds (#5530) 2023-03-14 23:33:31 +01:00
Matilda Smeds bfc43795f9 doc: explain testing in contributing guide (#5537)
* Add links to fundamental testing concepts in Rust
* Add information about conditional compilation attributes
  and how to use them to run tests with cargo
2023-03-12 21:01:58 +01:00
Tymoteusz Wiśniewski 89329cd07f io: add missing AsFd/AsHandle impls (#5540)
* io: add AsFd/AsHandle impls for stdio

* io: add AsFd impl for AsyncFd

* net: add AsHandle impl for named pipe types
2023-03-12 20:01:19 +01:00
Steven Fackler e34978233b io: add implementations of AsFd/AsHandle/AsSocket (#5514) 2023-03-11 17:04:01 +01:00
Andrew Halle 8eb94a33c0 time: fix a typo in timeout docs (#5538)
Replace instances of "immediatelly" with "immediately".
2023-03-11 10:40:19 +01:00
amab8901 2b7b1a0494 io: add async_io helper method to sockets (#5512) 2023-03-09 10:12:55 +00:00
Filipe Rodrigues 002f4a28c8 sync: add RwLockWriteGuard::{downgrade_map, try_downgrade_map} (#5527) 2023-03-08 17:06:08 +01:00
Tymoteusz Wiśniewski ff2f286c12 fs: fix File::from_raw_fd test (#5528) 2023-03-04 11:45:42 +01:00
Aaron Chen bd4ce68864 process: change "with regards" to "with regard to" in the docs (#5529) 2023-03-04 09:48:29 +00:00
Tymoteusz Wiśniewski abd92fb27f net: document usage of ready with stream halves (#5515) 2023-03-03 12:21:29 +01:00
Noah Kennedy 9931901d5c chore: list 1.25.x as LTS release (#5524) 2023-03-01 23:42:18 +00:00
Noah Kennedy a377240bbf chore: prepare for Tokio v1.26.0 release (#5521)
# 1.26.0 (March 1st, 2023)

### Fixed

- macros: fix empty `join!` and `try_join!` ([#5504])
- sync: don't leak tracing spans in mutex guards ([#5469])
- sync: drop wakers after unlocking the mutex in Notify ([#5471])
- sync: drop wakers outside lock in semaphore ([#5475])

### Added

- fs: add `fs::try_exists` ([#4299])
- net: add types for named unix pipes ([#5351])
- sync: add `MappedOwnedMutexGuard` ([#5474])

### Changed

- chore: update windows-sys to 0.45 ([#5386])
- net: use Message Read Mode for named pipes ([#5350])
- sync: mark lock guards with `#[clippy::has_significant_drop]` ([#5422])
- sync: reduce contention in watch channel ([#5464])
- time: remove cache padding in timer entries ([#5468])
- time: Improve `Instant::now()` perf with test-util ([#5513])

### Internal Changes

- io: use `poll_fn` in `copy_bidirectional` ([#5486])
- net: refactor named pipe builders to not use bitfields ([#5477])
- rt: remove Arc from Clock ([#5434])
- sync: make `notify_waiters` calls atomic ([#5458])
- time: don't store deadline twice in sleep entries ([#5410])

### Unstable

- metrics: add a new metric for budget exhaustion yields ([#5517])

### Documented

- io: improve AsyncFd example ([#5481])
- runtime: document the nature of the main future ([#5494])
- runtime: remove extra period in docs ([#5511])
- signal: updated Documentation for Signals ([#5459])
- sync: add doc aliases for `blocking_*` methods ([#5448])
- sync: fix docs for Send/Sync bounds in broadcast ([#5480])
- sync: document drop behavior for channels ([#5497])
- task: clarify what happens to spawned work during runtime shutdown ([#5394])
- task: clarify `process::Command` docs ([#5413])
- task: fix wording with 'unsend' ([#5452])
- time: document immediate completion guarantee for timeouts ([#5509])
- tokio: document supported platforms ([#5483])

[#4299]: https://github.com/tokio-rs/tokio/pull/4299
[#5350]: https://github.com/tokio-rs/tokio/pull/5350
[#5351]: https://github.com/tokio-rs/tokio/pull/5351
[#5386]: https://github.com/tokio-rs/tokio/pull/5386
[#5394]: https://github.com/tokio-rs/tokio/pull/5394
[#5410]: https://github.com/tokio-rs/tokio/pull/5410
[#5413]: https://github.com/tokio-rs/tokio/pull/5413
[#5422]: https://github.com/tokio-rs/tokio/pull/5422
[#5434]: https://github.com/tokio-rs/tokio/pull/5434
[#5448]: https://github.com/tokio-rs/tokio/pull/5448
[#5452]: https://github.com/tokio-rs/tokio/pull/5452
[#5458]: https://github.com/tokio-rs/tokio/pull/5458
[#5459]: https://github.com/tokio-rs/tokio/pull/5459
[#5464]: https://github.com/tokio-rs/tokio/pull/5464
[#5468]: https://github.com/tokio-rs/tokio/pull/5468
[#5469]: https://github.com/tokio-rs/tokio/pull/5469
[#5471]: https://github.com/tokio-rs/tokio/pull/5471
[#5474]: https://github.com/tokio-rs/tokio/pull/5474
[#5475]: https://github.com/tokio-rs/tokio/pull/5475
[#5477]: https://github.com/tokio-rs/tokio/pull/5477
[#5480]: https://github.com/tokio-rs/tokio/pull/5480
[#5481]: https://github.com/tokio-rs/tokio/pull/5481
[#5483]: https://github.com/tokio-rs/tokio/pull/5483
[#5486]: https://github.com/tokio-rs/tokio/pull/5486
[#5494]: https://github.com/tokio-rs/tokio/pull/5494
[#5497]: https://github.com/tokio-rs/tokio/pull/5497
[#5504]: https://github.com/tokio-rs/tokio/pull/5504
[#5509]: https://github.com/tokio-rs/tokio/pull/5509
[#5511]: https://github.com/tokio-rs/tokio/pull/5511
[#5513]: https://github.com/tokio-rs/tokio/pull/5513
[#5517]: https://github.com/tokio-rs/tokio/pull/5517
2023-03-01 22:09:48 +00:00
Noah Kennedy 52da177dea metrics: add a new metric for budget exhaustion yields (#5517) 2023-03-01 21:25:35 +01:00
Carl Lerche ee1c940709 time: Improve Instant::now() perf with test-util (#5513)
The test-util feature flag is only intended to be used with tests.
However, it is possible to enable it in release mode accidentally. This
patch reduces the overhead of `Instant::now()` when the `test-util`
feature flag is enabled but `time::pause()` is not called.

The optimization is implemented by adding a static atomic flag that
tracks if `time::pause()` has ever been called. In `Instant::now()`, the
atomic flag is first checked before the thread-local and mutex are
accessed.
2023-02-27 10:21:42 -08:00
Grachev Mikhail 815d89a407 runtime: remove extra period in docs (#5511) 2023-02-27 15:41:17 +01:00
Daria Sukhonina 54aaf3d0e3 time: document immediate completion guarantee for timeouts (#5509) 2023-02-27 14:17:31 +00:00
Tymoteusz Wiśniewski 5a3abe56ee net: add types for named unix pipes (#5351) 2023-02-27 09:39:07 +01:00
Alice Ryhl d44b1ca9c8 io: ignore SplitByUtf8BoundaryIfWindows test on miri (#5507)
These tests take a very long time under miri, but the code they're
testing isn't unsafe, so there isn't any reason to run them under miri.
2023-02-26 21:44:44 +00:00
Eric McBride e23c6f3935 signal: updated Documentation for Signals (#5459) 2023-02-26 19:43:41 +00:00
Alice Ryhl 0a50cb3baa net: fix test compilation failure (#5506) 2023-02-26 19:06:08 +00:00
Christopher Hunt 2298679af4 runtime: document the nature of the main future (#5494) 2023-02-26 16:48:56 +01:00
Chris Brody cadcd5da5e fs: add more tests for filesystem functionality (#5493) 2023-02-26 16:48:09 +01:00
Adrian Heine né Lang ca9f7ee9f4 macros: fix empty join! and try_join! (#5504)
Fixes: #5502
2023-02-25 18:06:17 +01:00
Hayden Stainsby c89406965f sync: document drop behavior for channels (#5497)
Some users mentioned that the behavior of a channel when the receivers
and/or senders are dropped isn't explicitly documented.

This change adds wording to the documentation for each channel in the
sync module, explaining under which conditions messages in a channel are
dropped with respect to dropping the senders and the receivers.

Refs: #5490
2023-02-23 11:04:12 +01:00
Predrag Gruevski cf486361d0 ci: remove cargo-semver-checks flags that are no longer necessary (#5496)
These flags were previously only needed due to a bug in the `cargo-semver-checks` CLI logic.

The correct behavior (available as of v0.18.3) for `cargo-semver-checks` is to ignore `publish = false` crates when scanning a workspace, *unless* those crates are specifically selected for checking.

All the crates being excluded here are `publish = false` so they are already excluded by the default behavior, so all `--exclude` flags are no-ops.
2023-02-22 18:54:17 +00:00
Alice Ryhl d7b7c61317 tokio: document supported platforms (#5483) 2023-02-21 19:57:19 +01:00
Kevin (Kun) "Kassimo" Qian 12f81ffa61 fs: add fs::try_exists (#4299) 2023-02-21 14:15:54 +01:00
Alice Ryhl 3ea5cc5a82 stream: fix changelog for 0.1.12 (#5488) 2023-02-20 16:19:56 +00:00
Konrad Borowski fa31cd9990 io: use poll_fn in copy_bidirectional (#5486) 2023-02-20 15:38:40 +01:00
Alice Ryhl 46f974d8cf chore: prepare tokio-stream v0.1.12 (#5484) 2023-02-20 10:18:18 +01:00
Alice Ryhl 018d0450c7 io: improve AsyncFd example (#5481) 2023-02-19 23:40:56 +01:00
Alice Ryhl ee09e04c31 sync: drop wakers after unlocking the mutex in Notify (#5471) 2023-02-19 22:16:24 +01:00
Chris Brody d07027f5bc sync: add WatchStream::from_changes (#5432) 2023-02-19 16:16:12 +01:00
Alice Ryhl 2e0372be6f sync: add MappedOwnedMutexGuard (#5474) 2023-02-19 14:12:32 +01:00
Tymoteusz Wiśniewski eca24068f7 sync: fix docs for Send/Sync bounds in broadcast (#5480) 2023-02-19 14:11:42 +01:00
Tymoteusz Wiśniewski 795754a846 sync: make notify_waiters calls atomic (#5458) 2023-02-19 14:10:38 +01:00
Alice Ryhl 0f17d69303 ci: remove PROPTEST_CASES from miri (#5478)
This option doesn't do anything anymore.
2023-02-19 11:11:22 +00:00
Maximilian Hils 2e7f996f17 net: refactor named pipe builders to not use bitfields (#5477) 2023-02-19 11:59:28 +01:00
amab8901 901f6d26c6 sync: drop wakers outside lock in semaphore (#5475) 2023-02-19 11:16:59 +01:00
Maximilian Hils a8fda87058 net: use Message Read Mode for named pipes (#5350) 2023-02-18 20:03:16 +01:00
tijsvd d7abdbb315 benches: mutex contention in watch::Receiver bench (#5472) 2023-02-18 14:51:08 +00:00
Alice Ryhl 24aac0add3 sync: don't leak tracing spans in mutex guards (#5469) 2023-02-18 10:39:25 +01:00
Alice Ryhl b921fe45ac sync: reduce contention in watch channel (#5464) 2023-02-17 23:56:56 +01:00
Alice Ryhl 0dc1b71e6e time: remove cache padding in timer entries (#5468) 2023-02-17 22:49:45 +01:00
Alice Ryhl d19f2f2d39 sync: add doc aliases for blocking_* methods (#5448) 2023-02-17 16:23:57 +01:00
Christopher Hunt e106c4d32b benches: benchmark for things in block_on (#5440)
This additional benchmark exercises a common request/reply pattern using an MPSC for requests along with a oneshot payload as a reply mechanism. When used in a current threaded scenario, the bench is 17 times faster on my machine than when using the multi-threaded runtime and one worker thread. Not only that, but if I increase the number of worker threads to 6, performance degrades further.

Does this suggest a scheduling problem with the multi-threaded runtime?

No matter what, hopefully the benchmarks are a useful addition.
2023-02-14 23:05:10 +00:00
Tim de Jager 28d6f4d509 task: fix wording with 'unsend' (#5452) 2023-02-14 12:44:05 +00:00
Finomnis d1da6c20d8 ci: always assume minor release in semver check (#5455) 2023-02-14 10:09:59 +01:00
Alice Ryhl e629ad7c9a chore: prepare tokio-util v0.7.7 (#5451) 2023-02-12 12:42:38 +01:00
Alice Ryhl 36fdccc3bc util: Revert "remove Encoder bound on FramedParts constructor" (#5450)
This reverts commit ae69d11d1f.
2023-02-12 11:55:41 +01:00
Alice Ryhl 01bb1ecf4d chore: prepare tokio-util v0.7.6 (#5447) 2023-02-10 10:48:36 +01:00
Alice Ryhl 36d2233579 chore: fix dependency on Tokio (#5445) 2023-02-10 10:13:37 +01:00
Alice Ryhl 74fb9e387a chore: prepare tokio-util v0.7.5 (#5442) 2023-02-09 17:35:53 +01:00
Alice Ryhl 8b44077ebc sync: make CancellationToken UnwindSafe (#5438) 2023-02-09 13:07:52 +01:00
Caio d6dbefcdc0 sync: mark lock guards with #[clippy::has_significant_drop] (#5422) 2023-02-09 11:20:09 +01:00
Conrad Ludgate d96bbf0465 time: don't store deadline twice in sleep entries (#5410) 2023-02-09 11:19:02 +01:00
Taiki Endo 09b2653e71 chore: update windows-sys to 0.45 (#5386) 2023-02-09 11:16:12 +01:00
Valentin 061325ba7e task: clarify what happens to spawned work during runtime shutdown (#5394) 2023-02-09 11:14:01 +01:00
Nathaniel Brough d7d5d05333 tests: port proptest fuzz harnesses to use cargo-fuzz (#5392)
This change ports fuzz tests from the black-box fuzzing framework,
proptest-rs over to use the grey-box fuzzing framework cargo-fuzz.

Refs: #5391
2023-02-09 11:08:50 +01:00
Finomnis 1dcfe1cc9b ci: add semver checking to CI (#5437) 2023-02-08 16:45:02 +01:00
Dmitry Ivanov 5653b4583c io: remove erroneous wake call in SinkWriter (#5436) 2023-02-07 18:32:27 +00:00
Carl Lerche abf5d28f2c rt: remove Arc from Clock (#5434)
This patch removes `Arc` from Tokio's internal clock source. Instead of
cloning `Clock` when needed, a reference is passed into functions that
need to get the current instant.
2023-02-07 09:45:14 -08:00
Taiki Endo a7945b469d ci: update Cirrus CI config (#5428)
* Use image_family for FreeBSD image in Cirrus CI
* Do not trigger Cirrus CI on branches other than master and tokio-.*
2023-02-07 03:58:19 +09:00
mTsBucy1 80ec80165b task: clarify process::Command docs (#5406) (#5413) 2023-01-30 16:47:04 +01:00
Steven Fackler 88b1eb54fb chore: prepare Tokio v1.25.0 release (#5408) 2023-01-29 22:44:31 +01:00
Jonathan Schwender 1f50c57185 metrics: fix steal_count docs, add steal_operations (#5330) 2023-01-27 20:44:47 +01:00
Flavio Moreira a18b3645f3 chore: update year in LICENSE files (#5402) 2023-01-27 16:05:48 +01:00
jake fe2dcb9453 io: increase MAX_BUF from 16384 to 2MiB (#5397) 2023-01-27 13:50:55 +01:00
Chris Wailes c90757f07a tests: condition unwinding tests on cfg(panic = "unwind") (#5384) 2023-01-21 11:12:24 +01:00
Taiki Endo f3f8e4f17f chore: update nix to 0.26 (#5385) 2023-01-21 12:17:04 +09:00
Carl Lerche 42bec96189 Merge branch 'tokio-1.24.x' into master 2023-01-17 12:59:09 -08:00
Carl Lerche 4f6a95badc chore: prepare Tokio v1.24.2 release 2023-01-17 12:26:13 -08:00
Carl Lerche 3d33610ed2 Merge branch 'tokio-1.20.x' into tokio-1.24.x 2023-01-17 12:25:05 -08:00
Carl Lerche 38a9c6c1a5 Merge branch 'tokio-1.20.x' into master 2023-01-17 11:24:22 -08:00
Carl Lerche f3ce29a003 chore: prepare Tokio v1.20.4 release 2023-01-17 11:09:42 -08:00
Carl Lerche 0d8fe5fe75 Merge branch 'tokio-1.18.x' into tokio-1.20.x 2023-01-17 11:08:06 -08:00
Taiki Endo 171ce0ff8d chore: prepare Tokio v1.18.5 release 2023-01-17 23:00:38 +09:00
Taiki Endo d6ea7a742b Add T: Unpin bound to ReadHalf::unsplit 2023-01-17 21:53:54 +09:00
Alice Ryhl 06f1a601bb task: clarify doc about tasks starting immediately (#5364) 2023-01-14 11:11:45 -08:00
Taiki Endo 40782efb76 tokio: fix remaining issues about atomic_u64_static_once_cell.rs (#5374)
Fixes #5373
Closes #5358 

- Add check for no_atomic_u64 & no_const_mutex_new (condition to atomic_u64_static_once_cell.rs is compiled)
- Allow unused_imports in TARGET_ATOMIC_U64_PROBE. I also tested other *_PROBE and found no other errors triggered by -D warning.
- Fix cfg of util::once_cell module
2023-01-14 11:11:05 -08:00
Steven Fackler c390a62387 Add broadcast::Sender::len (#5343)
* Add broadcast::Sender::len

* Add a randomized test for broadcast::Sender::len

* fix wasm build

* less silly cfg

* review feedback

* grammar?
2023-01-12 13:53:31 -05:00
Tymoteusz Wiśniewski f9dbfa8251 net: improve from_std docs regarding non-blocking IO (#5332) 2023-01-11 12:56:27 +00:00
Alice Ryhl 31c7e82919 chore: prepare Tokio v1.24.1 (#5357) 2023-01-06 10:48:42 +00:00
dtolnay 8d8db27442 tokio: add load and compare_exchange_weak to loom StaticAtomicU64 (#5356) 2023-01-06 15:19:31 +09:00
Carl Lerche dfe252d1fa chore: prepare Tokio v1.24.0 release (#5353) 2023-01-05 11:20:35 -08:00
Paul Loyd 21b233fa9c test: bump version of async-stream (#5347) 2023-01-05 11:02:07 +01:00
Carl Lerche 72993044e6 Merge branch 'tokio-1.23.x' into master 2023-01-04 11:36:07 -08:00
Carl Lerche 1a997ffbd6 chore: prepare Tokio v1.23.1 release 2023-01-04 10:32:38 -08:00
Carl Lerche a8fe333cc4 Merge branch 'tokio-1.20.x' into tokio-1.23.x 2023-01-03 15:06:02 -08:00
Carl Lerche ba81945ffc chore: prepare Tokio 1.20.3 release 2023-01-03 13:28:44 -08:00
Carl Lerche 763bdc967e ci: run WASI tasks using latest Rust
This should let CI to pass.
2023-01-03 13:28:43 -08:00
Carl Lerche 9f98535877 Merge remote-tracking branch 'origin/tokio-1.18.x' into fix-named-pipes-1.20 2023-01-03 13:12:20 -08:00
Carl Lerche 9241c3eddf chore: prepare Tokio v1.18.4 release 2023-01-03 13:06:27 -08:00
Carl Lerche 699573d550 net: fix named pipes server configuration builder
The `pipe_mode` function would erase any previously set configuration
option that is specified using the pipe_mode fit field. This patch fixes
the builder to maintain the bit field when changing the pipe mode.
2023-01-03 13:06:27 -08:00
Carl Lerche c6552c5680 rt: use internal ThreadId implementation (#5329)
The version provided by `std` has limitations, including no way to try
to get a thread ID without panicking.
2022-12-30 15:17:35 -08:00
Carl Lerche 048049f888 rt: move task::Id into its own file (#5327)
This is a minor internal cleanup.
2022-12-30 10:49:45 -08:00
Taiki Endo 98d484e29c ci: update cargo-check-external-types to 0.1.6 (#5325) 2022-12-30 19:03:44 +09:00
Taiki Endo ef0224246b tests: fix SB violation in LeakedBuffers (#5322) 2022-12-29 11:46:08 +09:00
icedrocket 4a4f80ca70 fs: use chunks in fs::read_dir (#5309) 2022-12-28 12:06:46 +01:00
Hyeonu Park 9af2f5ee59 io: optimize shutdown check on I/O operations (#5300)
The global flag remains and is used to prevent duplicated shutdowns and
new io operations after shutdown.

On shutdown, the driver flips the shutdown flag of every pending io
operations and wake them to fail with a shutdown error.

Fixes: #5227
2022-12-27 10:40:41 -08:00
Taiki Endo b75dba6904 ci: update Swatinem/rust-cache action to v2 (#5320) 2022-12-28 02:20:12 +09:00
Lencerf 353e5cabb8 process: fix typo in process::imp::Pipe comment (#5314)
Signed-off-by: Changyuan Lyu <[email protected]>
2022-12-27 15:50:12 +00:00
Alice Ryhl 8d58dc85b5 sync: document that there is no spsc and spmc channel (#5306) 2022-12-27 16:24:50 +01:00
Taiki Endo 519afd4458 ci: remove uses of unmaintained actions-rs actions (#5316)
- Use dtolnay/rust-toolchain instead of actions-rs/toolchain
- Use cargo/cross directly instead of actions-rs/cargo
- Use rustsec/audit-check instead of actions-rs/audit-check
2022-12-28 00:06:56 +09:00
Pure White 682e93df93 rt: read environment variable for worker thread count (#4250) 2022-12-21 15:43:35 +01:00
Alice Ryhl b9ae7e6659 signal: remove redundant Pin around globals (#5303) 2022-12-18 09:42:59 +01:00
Abutalib Aghayev d9e0f66113 task: rename State::has_join_waker to State::is_join_waker_set (#5248) 2022-12-17 22:34:12 +01:00
Alice Ryhl 6b3727d580 metrics: make num_idle_blocking_threads test less flaky (#5302) 2022-12-17 19:06:30 +01:00
Jason Orendorff e14ca72e68 test-util: don't auto-advance time when a spawn_blocking task is running (#5115) 2022-12-17 13:02:18 +01:00
John Nunley 42db755ac1 tokio: improve detection of whether a target supports AtomicU64 (#5284) 2022-12-16 19:53:35 +01:00
John Nunley 81b50e946f sync: decrease stack usage in mpsc channel (#5294) 2022-12-15 22:48:00 +01:00
Carl Lerche 39766220f4 rt: implement task::Id using StaticAtomicU64 (#5282)
This patch simplifies the implementation of `task::Id` by moving
conditional compilation into the `AtomicU64` definition. To handle
platforms that do not include `const fn Mutex::new()`, `StaticAtomicU64`
is defined as always having a `const fn new()`. `StaticAtomicU64` is
implemented with `OnceCell` when needed.
2022-12-10 13:49:16 -08:00
Matt Fellenz ae69d11d1f util: remove Encoder bound on FramedParts constructor (#5280) 2022-12-09 11:12:42 +00:00
Carl Lerche c693ccd210 ci: test no const mutex new (#5257)
This adds CI coverage for a couple of code paths that are not currently
hit in CI:

* no `const fn Mutex::new`
* no `AtomicU64`

This is done by adding some new CFG flags used only for tests in order
to force those code paths.
2022-12-09 02:13:22 +09:00
Divy Srivastava 36039d0bb9 rt: allow configuring I/O events capacity (#5186)
Adds a method `Builder::max_io_events_per_tick()` to the runtime builder. This can be used to configure the capacity of events that may be processed per OS poll.
2022-12-07 12:15:03 -06:00
Carl Lerche 22cff80048 chore: update CI's clippy version to 1.65 (#5276) 2022-12-06 19:56:13 -08:00
Alan Somers 07da5e73ee ci: update CI environment to FreeBSD 12.4 (#5272)
12.3 will soon be EoL
2022-12-06 10:03:51 +01:00
Alan Somers c4ed16d1b4 ci: future-proof for FreeBSD 12 (#5260)
Raise the mio-aio dev dependency, which transitively brings in Nix, to
ensure that the tests will continue to compile if libc switches from a
FreeBSD 11 ABI to a FreeBSD 12 one.
2022-12-06 10:03:09 +01:00
Carl Lerche 3ce5a2681c chore: prepare Tokio v1.23 release (#5270)
### Fixed
 - net: fix Windows named pipe connect ([#5208])
 - io: support vectored writes for `ChildStdin` ([#5216])
 - io: fix `async fn ready()` false positive for OS-specific events ([#5231])

 ### Changed
 - runtime: `yield_now` defers task until after driver poll ([#5223])
 - runtime: reduce amount of codegen needed per spawned task ([#5213])
 - windows: replace `winapi` dependency with `windows-sys` ([#5204])

 [#5208]: https://github.com/tokio-rs/tokio/pull/5208
 [#5216]: https://github.com/tokio-rs/tokio/pull/5216
 [#5213]: https://github.com/tokio-rs/tokio/pull/5213
 [#5204]: https://github.com/tokio-rs/tokio/pull/5204
 [#5223]: https://github.com/tokio-rs/tokio/pull/5223
 [#5231]: https://github.com/tokio-rs/tokio/pull/5231
2022-12-05 15:22:43 -08:00
Tymoteusz Wiśniewski 644cb8207d rt: fix *_closed false positives (#5231)
Readiness futures inconsistently return the current readiness of an I/O resource if it is immediately available, or all readiness relevant for the given `Interest`, if a future needs to wait. In particular, it always returns `read_closed` for `Interest::READABLE` and `write_closed` for `Interest::WRITABLE`, which often is not true. Tokio should not tolerate false positives for `*_closed` events because they are considered final states and are not cleared internally.

In the case of an `io_resource.ready(Interest::READABLE | Interest::WRITABLE)` call, this behavior may also lead to false positives of other events.

## Solution

Follow the same strategy as `poll_ready` and return the current resource's readiness.

Closes: #5098
2022-12-05 14:42:49 -08:00
Jiahao XU a1316cd792 io: impl std::io::BufRead on SyncIoBridge<T> (#5265)
Signed-off-by: Jiahao XU <[email protected]>
2022-12-05 10:11:44 +01:00
sharnoff 86ffabe2af docs: add note about current-thread + Handle::block_on (#5264)
There's already an existing warning about this combo in the
documentation for `Handle::block_on`. This commit adds a summarized
version in `Runtime::handle`.
2022-12-05 00:14:05 -06:00
Vitalii Kryvenko 00bf5ee8a8 sync: improve watch docs (#5261) 2022-12-04 00:06:12 +00:00
Tilman 87510100ce Fix typo (#5255) 2022-12-03 10:49:55 +00:00
Carl Lerche 2be71ad746 chore: move conditional AtomicU64 impl to new file (#5256)
Keeping the implementation out of a macro lets rustfmt apply to it.
2022-12-02 11:47:11 -08:00
Carl Lerche d1b789f33a rt: fix new yield_now behavior with block_in_place (#5251)
PR #5223 changed the behavior of `yield_now()` to store yielded tasks
and notify them *after* polling the resource drivers. This PR fixes a
couple of bugs with this new behavior when combined with
`block_in_place()`.

First, we need to avoid freeing the deferred task queue when exiting a
runtime if it is *not* the root runtime. Because `block_in_place()`
allows a user to start a new runtime from within an existing task, this
check is necessary.

Second, when a worker core is stolen from a thread during a
`block_in_place()` call, we need to ensure that deferred tasks are
notified anyway.
2022-12-01 17:23:33 -08:00
Carl Lerche 22862739dd rt: yield_now defers task until after driver poll (#5223)
Previously, calling `task::yield_now().await` would yield the current
task to the scheduler, but the scheduler would poll it again before
polling the resource drivers. This behavior can result in starving the
resource drivers.

This patch creates a queue tracking yielded tasks. The scheduler
notifies those tasks **after** polling the resource drivers.

Refs: #5209
2022-11-30 14:21:08 -08:00
Taiki Endo 993a60b7c7 chore: prepare tokio-macros v1.8.2 (#5246) 2022-11-30 22:10:13 +09:00
Taiki Endo 5d25ec46d5 macros: fix span of body variable (#5244) 2022-11-30 03:50:41 +09:00
Thomas de Zeeuw 766f22fae3 Prepare tokio-macros 1.8.1 2022-11-29 15:08:09 +00:00
Thomas de Zeeuw f5686f6bc0 Use #crate_ident in test macro
Instead of ::tokio.
2022-11-29 14:28:13 +00:00
Thomas de Zeeuw 224acd2500 Pin Future to stack in #[tokio::test]
Instead of boxing it.
2022-11-29 14:28:13 +00:00
Thomas de Zeeuw 2fcc6c2cb0 Box Futures in #[tokio::test]
This reduces the amount of copies of the Runtime::block_on and related
functions the compiler has to generate and LLVM process. We've seen it
reduce the compilation time of our tests (some 1900 of them) from 40s
down to 12s, with no impact on the runtime of tests.

Below is an output of llvm-lines for our tests.

Before:

  Lines                  Copies                Function name
  -----                  ------                -------------
  8954414                156577                (TOTAL)
   984626 (11.0%, 11.0%)   9289 (5.9%,  5.9%)  std::thread::local::LocalKey<T>::try_with
   648093 (7.2%, 18.2%)    1857 (1.2%,  7.1%)  tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}
   557100 (6.2%, 24.5%)    3714 (2.4%,  9.5%)  tokio::park::thread::CachedParkThread::block_on
   551679 (6.2%, 30.6%)    7430 (4.7%, 14.2%)  tokio::coop::with_budget::{{closure}}
   514389 (5.7%, 36.4%)    3714 (2.4%, 16.6%)  tokio::runtime::scheduler::current_thread::Context::enter
   326832 (3.6%, 40.0%)    1857 (1.2%, 17.8%)  tokio::runtime::scheduler::current_thread::CurrentThread::block_on
   291549 (3.3%, 43.3%)    1857 (1.2%, 19.0%)  tokio::runtime::scheduler::current_thread::CoreGuard::enter
   261907 (2.9%, 46.2%)    7430 (4.7%, 23.7%)  tokio::coop::budget
   189468 (2.1%, 48.3%)    7430 (4.7%, 28.5%)  tokio::coop::with_budget
   137418 (1.5%, 49.8%)    3714 (2.4%, 30.8%)  tokio::runtime::enter::Enter::block_on
   126276 (1.4%, 51.3%)    1857 (1.2%, 32.0%)  tokio::runtime::Runtime::block_on
   124419 (1.4%, 52.6%)    1857 (1.2%, 33.2%)  tokio::macros::scoped_tls::ScopedKey<T>::set
   118897 (1.3%, 54.0%)    3715 (2.4%, 35.6%)  core::option::Option<T>::or_else
   111420 (1.2%, 55.2%)    1857 (1.2%, 36.8%)  tokio::runtime::scheduler::current_thread::CurrentThread::block_on::{{closure}}
   109408 (1.2%, 56.4%)    2105 (1.3%, 38.1%)  <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
   105893 (1.2%, 57.6%)    9289 (5.9%, 44.0%)  std::thread::local::LocalKey<T>::with
    96564 (1.1%, 58.7%)    1857 (1.2%, 45.2%)  tokio::runtime::scheduler::current_thread::Context::run_task
    90993 (1.0%, 59.7%)    7428 (4.7%, 50.0%)  tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}
    90515 (1.0%, 60.7%)    2105 (1.3%, 51.3%)  core::pin::Pin<&mut T>::map_unchecked_mut
    89136 (1.0%, 61.7%)    1857 (1.2%, 52.5%)  tokio::runtime::scheduler::multi_thread::MultiThread::block_on

After:

  Lines                  Copies               Function name
  -----                  ------               -------------
  3188618                41634                (TOTAL)
   109408 (3.4%,  3.4%)   2105 (5.1%,  5.1%)  <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
    90515 (2.8%,  6.3%)   2105 (5.1%, 10.1%)  core::pin::Pin<&mut T>::map_unchecked_mut
    56220 (1.8%,  8.0%)   1874 (4.5%, 14.6%)  alloc::boxed::Box<T>::pin
    48333 (1.5%,  9.5%)   2179 (5.2%, 19.8%)  core::ops::function::FnOnce::call_once
    28587 (0.9%, 10.4%)      1 (0.0%, 19.8%)  XXXXXXXXXXXXXXXXXXX
    18730 (0.6%, 11.0%)   1873 (4.5%, 24.3%)  alloc::boxed::Box<T,A>::into_pin
    16190 (0.5%, 11.5%)      2 (0.0%, 24.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    15870 (0.5%, 12.0%)      2 (0.0%, 24.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    15250 (0.5%, 12.5%)      1 (0.0%, 24.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXX
    12801 (0.4%, 12.9%)      2 (0.0%, 24.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    12801 (0.4%, 13.3%)      2 (0.0%, 24.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    12630 (0.4%, 13.7%)   2105 (5.1%, 29.4%)  <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::{{closure}}
    12613 (0.4%, 14.1%)      2 (0.0%, 29.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    12613 (0.4%, 14.5%)      2 (0.0%, 29.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    12613 (0.4%, 14.9%)      2 (0.0%, 29.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    12613 (0.4%, 15.3%)      2 (0.0%, 29.4%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    11395 (0.4%, 15.7%)     96 (0.2%, 29.7%)  alloc::alloc::box_free
    11364 (0.4%, 16.0%)   1891 (4.5%, 34.2%)  <T as core::convert::Into<U>>::into
    11238 (0.4%, 16.4%)   1873 (4.5%, 38.7%)  alloc::boxed::<impl core::convert::From<alloc::boxed::Box<T,A>> for core::pin::Pin<alloc::boxed::Box<T,A>>>::from
    10735 (0.3%, 16.7%)      2 (0.0%, 38.7%)  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Note that I have replaced our test functions with XXX. As you can
clearly see they're not in the top 20 in the before output, while
they're in the after oput.

Further note that the amount of copies have been reduced from 156577 to
41634.
2022-11-29 14:28:13 +00:00
Tymoteusz Wiśniewski 28ec4a6161 net: update try_io docs with interest limitations (#5222) 2022-11-28 10:38:40 +01:00
Loong Dai 939b5bb42f tests: fix a typo (#5236)
Signed-off-by: Loong <[email protected]>
2022-11-28 10:37:22 +01:00
Abutalib Aghayev 718d6ce8ca task: fix the incomplete/wrong description of JOIN_WAKER bit. (#5217)
* task: fix the incomplete/wrong description of JOIN_WAKER bit (#5217)
2022-11-24 15:47:15 -05:00
Tymoteusz Wiśniewski e316428210 net: replace socket with pipe in named pipe docs (#5221) 2022-11-23 13:48:30 +01:00
Taiki Endo fc83e01949 chore: add tokio_no_atomic_u64 cfg (#5226) 2022-11-23 19:00:57 +09:00
Loong Dai 3a5f7b7f2f examples: update hello world comment (#5219) 2022-11-23 11:00:25 +01:00
Loong Dai 6da81471f9 signal: fix a typo (#5224) 2022-11-23 10:59:44 +01:00
Kenny Kerr 299bd6aee3 net: replace winapi with windows-sys (#5204) 2022-11-22 16:23:26 +00:00
Loong Dai e14307393a runtime: fix typo in runtime builder docs (#5218)
Signed-off-by: Loong <[email protected]>
2022-11-22 08:24:12 +00:00
Alice Ryhl 45e37dbfa2 runtime: reduce codegen per task (#5213)
This PR should hopefully reduce the amount of code generated per
future-type spawned on the runtime. The following methods are no longer generic:

* `try_set_join_waker`
* `remote_abort`
* `clone_waker`
* `drop_waker`
* `wake_by_ref`
* `wake_by_val`

A new method is added to the vtable called schedule, which is used when a task
should be scheduled on the runtime. E.g. wake_by_ref will call it if the state change
says that the task needs to be scheduled. However, this method is only generic over
the scheduler, and not the future type, so it also isn't generated for every task.

Additionally, one of the changes involved in the above makes it possible to remove
the id field from JoinHandle and AbortHandle.
2022-11-21 15:38:22 -08:00
Jiahao XU 304b5152a7 sync: add owned future for CancellationToken (#5153) 2022-11-21 15:03:09 +00:00
Joonas Koivunen f15d14ee91 process: support ChildStdin::poll_write_vectored on unix (#5216) 2022-11-21 13:57:24 +00:00
Alice Ryhl 6a2cd9a652 doc: update parking_lot info in feature list (#5215) 2022-11-21 13:42:55 +01:00
Tymoteusz Wiśniewski 2682c505e8 net: fix named pipe connect (#5208) 2022-11-20 21:02:13 +00:00
Carl Lerche 808d52563e ci: run tests on ARM and i686 using cross (#5196)
This patch updates CI to use `cross` to run Tokio tests on virtualized
ARM and i686 VMs. Because ipv6 doesn't work on Github action running in
a docker instance, those tests are disabled
2022-11-18 14:02:53 -08:00
Alice Ryhl bf31759bff chore: prepare Tokio v1.22.0 (#5203) 2022-11-18 13:15:06 -08:00
John DiSanti d65826236b ci: remove libc types from external types allow list (#5197) 2022-11-17 11:57:55 +01:00
Lucas Kent 1cbbcc9ad5 sync: specify return type of oneshot::Receiver in docs (#5198) 2022-11-17 11:56:56 +01:00
Abutalib Aghayev a668020150 net: remove libc type leakage in a public API (#5191) 2022-11-15 23:28:33 +01:00
Alice Ryhl 01f0193971 chore: fix compilation on master (#5190) 2022-11-13 13:21:08 +00:00
Abutalib Aghayev 71bd49e146 task: add task::id() and task::try_id() (#5171) 2022-11-13 14:18:42 +01:00
Artyom Kozhemiakin 582d512907 sync: add mpsc::WeakUnboundedSender (#5189)
Signed-off-by: Artyom Kozhemiakin <[email protected]>
2022-11-12 22:29:13 +00:00
Carl Lerche b7812c85ca rt: fix LocalSet drop in thread local (#5179)
`LocalSet` cleans up any tasks that have not yet been completed when it is
dropped. Previously, this cleanup process required access to a thread-local.
Suppose a `LocalSet` is stored in a thread-local itself. In that case, when it is
dropped, there is no guarantee the drop implementation will be able to
access the internal `LocalSet` thread-local as it may already have been
destroyed.

The internal `LocalSet` thread local is mainly used to avoid writing unsafe
code. All `LocalState` that cannot be moved across threads is stored in the
thread-local and accessed on demand.

This patch moves this local-only state into the `LocalSet`'s "shared" struct.
Because this struct *is* `Send`, the local-only state is stored in `UnsafeCell`,
and callers must ensure not to touch it from other threads.

A debug assertion is added to enforce this requirement in tests.

Fixes #5162
2022-11-10 10:06:25 -08:00
Abutalib Aghayev 9e3fb1673a rt: move CoreStage methods to Core (#5182) 2022-11-10 13:15:30 +00:00
Carl Lerche 53cba023da rt: fix accidental unsetting of current handle (#5178)
An earlier change updated `enter_runtime` to also set the current
handle. However, the change did not store the `SetCurrentGuard`, so the
"current handle" was immediately unset. This patch stores the
`SetCurrentGuard` in the `EnterRuntimeGuard`.

No existing test exposed this bug because all tests went via `Runtime`
instead of `Handle`. Currently, `Runtime` is still explicitly setting
the handle before entering runtime, so all tests still passed. A new
test is added that covers the case of calling `Handle::block_on` and
accessing the current handle.
2022-11-09 12:13:30 -08:00
Carl Lerche 236d026667 rt: combine context and entered thread-locals (#5168)
A previous patch moved code related to entering a runtime into the
context module but did not change anything. This patch combines both
thread-local variables.
2022-11-07 13:35:54 -08:00
Alice Ryhl 909439c9f5 task: elaborate safety comments in task deallocation (#5172) 2022-11-06 22:13:25 +01:00
Alice Ryhl 9884fe3394 runtime: fix unsync_load on atomic types (#5175) 2022-11-06 14:38:18 +01:00
Alice Ryhl a1002a2203 ci: update miri flags (#5174) 2022-11-06 13:41:53 +01:00
Alice Ryhl fc9518b627 chore: bump clippy version (#5173) 2022-11-06 12:44:26 +01:00
Yiyu Lin f4643608ad runtime: fix typo in expect message (#5169) 2022-11-05 11:18:27 +00:00
Carl Lerche 687aa2bae5 rt: move enter into context (#5167)
This moves the functions, types, and thread-local related to entering a
runtime into the context module. This does not yet unify the thread-local
variables, as that, will be done in a follow-up PR.
2022-11-04 15:08:51 -07:00
Carl Lerche b2f5dbea47 rt: remove handle reference from each scheduler (#5166)
Instead of each scheduler flavor holding a reference to the scheduler
handle, the scheduler handle is passed in as needed. This removes a
duplicate handle reference in the `Runtime` struct and lays the
groundwork for further handle struct tweaks.
2022-11-04 13:36:12 -07:00
Duarte Nunes 23fdd32b01 rt: export metrics about the blocking thread pool (#5161)
Publish the blocking thread pool metrics as thread-safe values, written
under the blocking thread pool's lock and able to be read in a lock-free
fashion by any reader.

Fixes #5156
2022-11-04 11:05:36 -07:00
Hubert Hirtz 5b46395a1e sync: fix Sync assertion for AtomicWaker (#5165) 2022-11-04 13:22:30 +01:00
Carl Lerche 32da1aa9da rt: unify entering a runtime with Handle::enter (#5163)
This is a first step towards unifying the concepts of "entering a
runtime" and setting `Handle::current`.

Previously, these two operations were performed separately at each call
site (runtime block_on, ...). This is error-prone and also requires
multiple accesses to the thread-local variable. Additionally, "entering
the runtime" conflated the concept of entering a blocking region. For
example, calling `mpsc::Receiver::recv_blocking` performed the "enter
the runtime" step. This was done to prevent blocking a runtime, as the
operation will panic when called from an existing runtime.

To untangle these concepts, the patch splits out each logical operation
into functions. In total, there are three "enter" operations:

* `set_current_handle`
* `enter_runtime`
* `enter_blocking_region`

There are some behavior changes with each function, but they
should not translate to public behavior changes. The most significant is
`enter_blocking_region` does not change the value of the thread-local
variable, which means the function can be re-entered. Since
`enter_blocking_region` is an internal-only function and we do not
re-enter, this has no public-facing impact.

Because `enter_runtime` takes a `&Handle` to combine the
`set_current_handle` operation with entering a runtime, the patch
exposes an annoyance with the current `scheduler::Handle` struct layout.
A new instance of `scheduler::Handle` must be constructed at each call
to `enter_runtime`. We can explore cleaning this up later.

This patch also does not combine the "entered runtime" thread-local
variable with the "context" thread-local variable. To keep the patch
smaller, this has been punted to a follow-up change.
2022-11-03 15:01:08 -07:00
Carl Lerche df6348fb4a chore: fix tests for Rust 1.65 release (#5164)
Rust 1.65 reduces some struct sizes.
2022-11-03 14:24:10 -07:00
Rustom Shareef 74a29be607 chore: typo in TryLockError for RwLock::try_write (#5160)
Fixes an incoherent sentence describing when RwLock::try_write (and related) would error with TryLockError.
2022-11-02 18:13:31 -05:00
Carl Lerche 26791a62bc rt: move Runtime into its own file (#5159)
This removes the `Runtime` implementation from a cfg macro so it can be
formatted.
2022-11-02 15:44:56 -07:00
Carl Lerche 467adec4e1 rt: move park logic into runtime module (#5158)
The runtime is the primary user of parking. Moving park into runtime
will help future cleanups around combining context entering w/ block_on
calls.
2022-11-02 14:37:44 -07:00
Carl Lerche d8ee205530 rt: move budget state to context thread-local (#5157)
This patch consolidates the budget thread-local state with the
`runtime::context` thread local. This reduces the number of thread-local
variables used by Tokio by one.
2022-11-02 12:24:12 -07:00
Carl Lerche ca8e176ce9 rt: rm coop::budget from LocalSet::run_until (#5155)
The `LocalSet::run_until` future is just a "plain" future that should
run on a runtime that already has a coop budget. In other words, the
`run_until` future should not get its own budget but should inherit the
calling task's budget. Getting this behavior is done by removing the
call to `budget` in `run_until`.
2022-11-01 14:03:01 -07:00
Carl Lerche a051ed726f rt: move coop mod into runtime (#5152)
This is a step towards unifying thread-local variables. In the future,
`coop` will be updated to use the runtime context thread-local to store
its state.
2022-11-01 09:03:56 -07:00
Yiyu Lin 203a079743 sync: make Notify panic safe (#5154) 2022-11-01 14:24:01 +01:00
Carl Lerche b1f40f4356 rt: rename some confusing internal variables/fns (#5151)
This patch does some internal renames to remove some confusion.

* `allow_blocking` is renamed to `allow_block_in_place` to indicate that
  the variable only impacts the `block_in_place()` function.

* `context::try_enter` is renamed to `context::try_set_current` to
  disambiguate between the various "enter" functions. This function only
  sets the runtime handle used by Tokio's public APIs. Entering a runtime
  is a separate operation.  # Please enter the commit message for your
  changes.

* `scheduler::Handle::enter()` is removed to consolidate methods that
  set the current context.
2022-10-31 15:06:37 -07:00
Alice Ryhl a9d5eb2fc7 io: add lines example for StreamReader (#5145) 2022-10-31 20:40:52 +01:00
Matt Schulte c2210dfe37 net: fix function name in UdpSocket recv documentation (#5150)
In the "cancellation safety" section of the UdpSocket recv function, "recv_from" is referenced when it should be "recv"
2022-10-31 16:10:26 +00:00
Carl Lerche df99428c17 rt: add runtime::context to unify thread-locals (#5143)
This patch is the first step towards unifying all the thread-local
variables spread out across Tokio. A new `Context` struct is added which
will be used to replace the various thread-locals that exist today.

Initially, `Context` only holds the current runtime handle and the
random number generator. Further PRs will add other thread-local state.

A previous PR removed `runtime::context`. At that time,
`runtime::context` was used as an extra layer to access the various
runtime driver handles. This version of `runtime::context` serves a
different purpose (unifying all the thread-locals).
2022-10-31 09:05:10 -07:00
Vitaly Shukela d1a8ec6495 sync: add Semaphore::MAX_PERMITS (#5144) 2022-10-30 21:19:37 +00:00
Abutalib Aghayev fe1843c0e0 rt: add Handle::runtime_flavor (#5138) 2022-10-30 15:26:07 +00:00
Stepan Koltsov 15b362d2dd sync: name mpsc semaphore types (#5146)
Make code easier to read. No functional/perf changes.
2022-10-30 15:38:48 +01:00
620880f4ca io: add tokio_util::io::{CopyToBytes, SinkWriter} (#5070)
Co-authored-by: Alice Ryhl <[email protected]>
Co-authored-by: Simon Farnsworth <[email protected]>
2022-10-30 11:04:22 +00:00
Duarte Nunes 29c6de0e3e sync: add PollSemaphore::poll_acquire_many (#5137) 2022-10-30 10:06:10 +01:00
Sebastian Meßmer 3886a3eaf4 sync: add Mutex::blocking_lock_owned (#5130) 2022-10-29 14:59:40 +00:00
Ryan Thomas 3b5ef4eb98 time: document that timeouts check only before poll (#5126) 2022-10-29 14:59:29 +00:00
crusader-mike cbbf81b922 codec: expose backpressure_boundary in Framed API (#5124) 2022-10-29 14:59:22 +00:00
Harvey Hunt 1ab80ba580 process: add Command::process_group (#5114) 2022-10-29 14:59:15 +00:00
Carl Lerche 7483509746 rt: keep driver cfgs in driver.rs (#5141)
This patch removes driver related cfg_* macro calls from `scheduler` in
favor of keeping it in the driver module.
2022-10-28 13:04:09 -07:00
Carl Lerche 121f839b4b rt: remove rng_seed+mt test and update docs (#5142)
While setting the random number generator seed with the multi-threaded
scheduler does result in deterministic behavior related to the random
number generator, threads still introduce non-determinism, making it
hard (impossible?) to test this. There also is little value in doing so.

This patch also updates the docs to remove mention of work stealing.
2022-10-28 11:55:34 -07:00
Lucio Franco b749013a54 test: Improve tokio_test::task docs (#5132) 2022-10-28 13:55:13 -04:00
Carl Lerche 2f24451434 rt: remove runtime::context module (#5140)
The current runtime thread-local is moved to `runtime::scheduler` as
well as methods to enter and access the current handle.
2022-10-28 10:39:44 -07:00
Carl Lerche 5c2e275659 rt: move internal clock fns out of context (#5139)
A step towards getting rid of `runtime::context`. Internal functions
related to getting the current clock are moved to the time driver.
2022-10-27 14:18:39 -07:00
Carl Lerche 6c19748f90 rt: use signal driver handle via scheduler::Handle (#5135)
The signal driver still uses an `Arc` internally to track if the driver
is still running, however, using the `scheduler::Handle` to access the
signal driver handle lets us delete some code.
2022-10-27 13:07:51 -07:00
Carl Lerche 32d68fe579 rt: remove Arc from I/O driver (#5134)
The next step in the great driver cleanup. This patch removes the Arc
used in the I/O driver in favor of `runtime::scheduler::Handle`.
2022-10-27 11:13:25 -07:00
Hayden Stainsby 4bcd08b938 rt: fix rng_seed test for threaded runtime (#5133)
The improvement to the `rng_seed` tests added in #5075 missed a case in
the `rt_threaded` tests which was still checking for a specific value.
As described in that PR, this makes the tests fragile and changing tokio
internals may require updating the test.

This change fixes that half-implemented improvement so that the tests no
longer depend on the exact internal ordering, but rather compare two
runs of separate runtimes built with the same seed to check that the
results are the same.
2022-10-27 18:29:30 +02:00
Carl Lerche cb67f28fe3 rt: switch io::handle refs with scheduler:Handle (#5128)
The `schedule::Handle` reference is the internal runtime handle. This
patch replaces owned refs to `runtime::io::Handle` with
`scheduler::Handle`.
2022-10-27 08:51:03 -07:00
Carl Lerche 58c457190b rt: start decoupling I/O driver and I/O handle (#5127)
This is the start of applying a similar treatment to the I/O driver as
the time driver. The I/O driver will no longer hold its own reference to
the I/O handle. Instead, the handle is passed in when needed.

This patch also moves the process driver to the `runtime` module.
2022-10-26 12:07:38 -07:00
Carl Lerche ec66a92b01 rt: signal driver now uses I/O driver directly (#5125)
The signal driver uses a `UnixStream` to receive signal events.
Previously, the signal driver used `PollEvented` internally to receive
events on the `UnixStream`. However, using `PollEvented` from
within a runtime driver created a circular link between the runtime and
the `PollEvented` instance.

This patch replaces `PollEvented` usage in favor of accessing the I/O
driver directly. The I/O driver now reserves a token for signal-related
events and tracks signal readiness internally. The signal driver queries
the I/O driver to check for signal-related readiness.
2022-10-26 10:17:59 -07:00
Carl Lerche 1ca17bef67 rt: move signal driver to runtime module (#5121)
The signal feature only requires a driver with unix platforms. The
unix signal driver uses the I/O driver. A future refactor would like to
make the signal driver use internal APIs of the I/O driver. To do this,
the signal driver must be moved to the runtime module.
2022-10-24 15:51:18 -07:00
Carl Lerche 80568dfc6d rt: misc time driver cleanup (#5120)
Removes an unnecessary `Arc` and reduces internal state clones.
2022-10-24 13:59:47 -07:00
Alice Ryhl b248be2879 task: document that spawned tasks execute immedaitely (#5117) 2022-10-23 20:25:12 +02:00
Alice Ryhl d32ba2cf9d time: document return type of timeout (#5118) 2022-10-22 19:23:40 +02:00
Carl Lerche a03e042024 rt: remove a reference to internal time handle (#5107)
This patch removes a handle to the internal runtime driver handle held
by the runtime. This is another step towards reducing the number of Arc
refs across the runtime internals. Specifically, this change is part of
an effort to remove an Arc in the time driver itself.
2022-10-17 13:26:11 -07:00
cjw 00082c668f time: panic in release mode when mark_pending called illegally (#5093) 2022-10-16 08:46:57 +02:00
cjw 607816491d runtime: update the alignment of CachePadded (#5106) 2022-10-15 11:11:10 +02:00
afajl 1e437595a3 stream: document that throttle operates on ms granularity (#5101) 2022-10-14 23:45:16 +02:00
Alice Ryhl bf5eed8fa0 time: remove Unpin bound on Throttle methods (#5105) 2022-10-14 08:44:30 +00:00
Lukas Wirth 37d1d09d4a macros: reduce usage of last statement spans in proc-macros (#5092)
This excludes the initial let statement of the proc-macro expansion
from receiving the last statement spans to aid completions in rust-analyzer.
The current span confuses rust-analyzer as it will map the tail expression
tokens to the let keyword (as this is the first token it finds with the
same span) which currently breaks completions. This commit should not
degrade the initial intent of the span reusages, as the type mismatch
parts are still spanned appropriately.
2022-10-14 09:50:09 +02:00
Alice Ryhl 6929decf2c macros: don't take ownership of futures in macros (#5087) 2022-10-14 09:45:31 +02:00
Carl Lerche f8097437dd rt: remove a conditional compilation clause (#5104)
The `LocalSet` implementation includes a conditional compilation clause
that removes the `const` statement from the `thread_local` definition.
However, there already is an internal macro that does this:
`tokio_thread_local`.

This patch removes the conditional compilation in favor of using the
`tokio_thread_local` macro. This also fixes a conditional compilation
issue with an internal utility (`RcCell`).
2022-10-13 16:45:15 -07:00
Carl Lerche 964535eab0 tokio: rename internal thread_local macro (#5103)
Tokio maintains an internal thread_local macro that abstracts some
conditional build logic. Before this patch, the macro was named the same
as the `std` macro (`thread_local`). This resulted in confusion as to
whether or not the internal macro or the std macro was being called.

This patch renames the internal macro to `tokio_thread_local` making it
more obvious.
2022-10-13 14:29:12 -07:00
Eliza Weisman 23a1ccf24f task: wake local tasks to the local queue when woken by the same thread (#5095)
Motivation

Currently, when a task spawned on a `LocalSet` is woken by an I/O driver
or time driver running on the same thread as the `LocalSet`, the task is
pushed to the `LocalSet`'s locked remote run queue rather than to its
unsynchronized local run queue. This is unfortunate, as it
negates some of the performance benefits of having an unsynchronized
local run queue. Instead, tasks are only woken to the local queue when
they are woken by other tasks also running on the local set.

This occurs because the local queue is only used when the `CONTEXT`
thread-local contains a Context that's the same as the task's
`Schedule` instance (an `Arc<Shared>`)'s Context. When the `LocalSet`
is not being polled, the thread-local is unset, and the local run queue
cannot be accessed by the `Schedule` implementation for `Arc<Shared>`.

Solution

This branch fixes this by moving the local run queue into Shared along
with the remote run queue. When an `Arc<Shared>`'s Schedule impl wakes
a task and the `CONTEXT` thread-local is None (indicating we are not
currently polling the LocalSet on this thread), we now check if the
current thread's `ThreadId` matches that of the thread the `LocalSet`
was created on, and push the woken task to the local queue if it was.

Moving the local run queue into `Shared` is somewhat unfortunate, as it
means we now have a single field on the `Shared` type, which must not be
accessed from other threads and must add an unsafe impl `Sync` for `Shared`.
However, it's the only viable way to wake to the local queue
from the Schedule impl for `Arc<Shared>`, so I figured it was worth
the additional unsafe code. I added a debug assertion to check that the
local queue is only accessed from the thread that owns the `LocalSet`.
2022-10-13 11:27:19 -07:00
Eliza Weisman ca9dd726b1 runtime: fix Stacked Borrows violation in LocalOwnedTasks (#5099)
## Motivation

It turns out that `LocalSet` has...never actually passed Miri. This is
because all of the tests for `LocalSet` are defined as integration tests
in `tokio/tests/task_local_set.rs`, rather than lib tests in
`tokio/src`, and we never run Miri for integration tests.

PR #5095 added a new test reproducing an unrelated bug in `LocalSet`,
which had to be implemented as a lib test, as it must make internal
assertions about the state of the `LocalSet` that cannot be tested with
just the public API. This test failed under Miri, and it turns out that
the reason for this is unrelated to the change in #5095 --- `LocalSet`
uses the `LocalOwnedTasks` type, which turns out to contain a stacked
borrows violation due to converting an `&Header` into an
`NonNull<Header>` when removing a task from the `LocalOwnedTasks` list.

## Solution

Fortunately, this was actually quite easy to fix. The non-`Local`
version of `OwnedTasks` already uses `Task::header_ptr()` to get a
`NonNull<Header>` in its version of `remove`, which avoids this issue.
Therefore, the fix was as simple as updating `LocalOwnedTasks` to do the
same.

I've also added a very simple lib test in `src/task/local_set.rs` that
just creates a `LocalSet` and spawns a single task on it under a
current-thread runtime. This test fails under Miri without the fix in
this PR: https://github.com/tokio-rs/tokio/actions/runs/3237072694/jobs/5303682530

We should probably keep the test so that we're always testing at least
the most trivial `LocalSet` usage under Miri...
2022-10-12 19:18:34 +00:00
Makro ae0d49d59c chore: release tokio-stream v0.1.11 (#5094) 2022-10-11 16:48:24 +02:00
cjw 992a168122 runtime: remove Option around mio::Events in io driver (#5078) 2022-10-07 16:47:33 +02:00
Hayden Stainsby 9b486357ed rt: improve rng_seed test robustness (#5075)
The original tests for the `Builder::rng_seed` added in #4910 were a bit
fragile. There have already been a couple of instances where internal
refactoring caused the tests to fail and need to be modified. While it
is expected that internal refactoring may cause the random values to
change, this shouldn't cause the tests to break.

The tests should be more robust and not be affected by internal
refactoring or changes in the Rust compiler version. The tests are
changed to perform the same operation in 2 runtimes created with the
same seed, the expectation is that the values that result from each
runtime are the same.
2022-10-05 14:31:08 +02:00
Alice Ryhl fdc28bc883 coop: fix flaky coop test (#5074) 2022-10-05 12:55:02 +02:00
xudong.w 5dbd8ca8d4 chore: use std::AtomicPtr and std::AtomicU8 (#5071) 2022-10-04 10:06:24 +00:00
Anders Kiel Hovgaard ff4ab49bcf net: fix doc typos for TCP and UDP set_tos methods (#5073) 2022-10-03 13:28:50 -05:00
Simon Farnsworth 6bdcb813c6 io: make copy continue filling the buffer when writer stalls (#5066) 2022-10-03 12:58:21 +02:00
Ashish Kurmi b821e436c5 ci: add minimum GitHub token permissions for workflows (#5072)
Signed-off-by: Ashish Kurmi <[email protected]>
2022-10-03 05:15:23 -04:00
Alice Ryhl f4e08aec66 tokio: use const Mutex::new for globals (#5061) 2022-09-28 21:21:31 +02:00
Simon Farnsworth 96fab053ab io: wrappers for inspecting data on IO resources (#5033) 2022-09-28 18:21:51 +00:00
Simon Farnsworth 9b87daad7e net: don't use port 8080 in tests (#5062) 2022-09-28 11:26:24 +00:00
Erwan e8354279fb time: add DelayQueue::try_remove (#5052) 2022-09-28 07:50:00 +00:00
Serge Barral 78fc94099b runtime: mitigate ABA with 32-bit queue indices when possible (#5042)
When 64-bit atomics are supported, use 32-bit queue indices. This
greatly improves resilience to ABA and has no impact on performance on
64-bit platforms.

Fixes: #5041
2022-09-27 23:02:40 +00:00
Marek Kuskowski 2df45234ef stream: fix panic in ChunksTimeout::new (#5036) 2022-09-27 22:34:08 +00:00
grydholt aedcec666d io: fix doc for write_i8 to use signed integers (#5040)
Fixes: #5039
2022-09-27 22:08:20 +00:00
Dom 909de08845 sync: add merge() to semaphore permits (#4948) 2022-09-27 23:51:47 +02:00
Carl Dong 3db330dad2 examples: use write_all instead of write in hello world example (#5044) 2022-09-27 21:50:17 +00:00
Alice Ryhl feef48fb58 ci: improve minrust check and re-enable example (#5060) 2022-09-27 21:18:13 +00:00
Alice Ryhl 47b6e194fb Merge 'tokio-1.21.2' into 'master' (#5059) 2022-09-27 21:53:36 +02:00
Alice Ryhl a79b824faa chore: prepare Tokio v1.21.2 (#5058) 2022-09-27 21:42:23 +02:00
Alice Ryhl 3fbf314985 Merge 'tokio-1.20.2' into 'tokio-1.21.x' (#5057) 2022-09-27 21:13:45 +02:00
Alice Ryhl 3d95a4626f chore: prepare Tokio v1.20.2 (#5055) 2022-09-27 21:05:16 +02:00
Alice Ryhl 2063d6692e Merge 'tokio-1.18.3' into 'tokio-1.20.x' (#5054) 2022-09-27 10:48:37 +02:00
Alice Ryhl 5c76d070e2 chore: prepare Tokio v1.18.3 (#5051) 2022-09-27 09:42:51 +02:00
Alice Ryhl 05e661490b chore: don't use once_cell for 1.18.x LTS release (#5048)
The latest release of once_cell has an MSRV that is incompatible with the MSRV of the 1.18.x LTS release.
2022-09-26 10:41:35 +02:00
Hayden Stainsby 7096a80075 task: add track_caller to block_in_place and spawn_local (#5034)
Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds `#[track_caller]` to two public APIs in tokio task
module which weren't added in #4848.
* `tokio::task::block_in_place`
* `tokio::task::spawn_local`

These APIs had call stacks that went through closures, which is a use
case not supported by `#[track_caller]`. These two cases have been
refactored so that the `panic!` call is no longer inside a closure.

Tests have been added for these two new cases.

Refs: #4413
2022-09-20 22:55:51 +02:00
Carl Lerche d69e5bebf1 chore: release tokio-stream 0.1.10 (#5028)
Closes #5011
2022-09-18 10:11:03 -07:00
Carl Lerche 0b92f80a65 rt: rm internal Unpark types for Handle types (#5027)
This patch removes all internal `Unpark` runtime types. The runtime now
uses the `Handle` types (`runtime::io::Handle` and
`runtime::time::Handle`) to signal threads to unpark.

Without separate `Unpark` types, future patches will be able to remove
more `Arc`s used inside various drivers.
2022-09-18 10:10:49 -07:00
Carl Lerche cba5c1009e rt: move driver unpark out of multi-thread parker (#5026)
This patch removes the driver Unpark handle out of the multi-thread
parker and passes a reference in when it is needed. This is a first step
towards getting rid of the separate driver unpark handle in favor of
just using the regular driver handle. Because the regular driver handle
is owned at a higher level (at the top of the worker struct).
2022-09-17 16:46:44 -07:00
Carl Lerche cdd6eeaf70 rt: update MultiThread to use its own Handle (#5025)
This is the equivalent as tokio-rs/tokio#5023, but for the MultiThread
scheduler. This patch updates `MultiThread` to use `Arc<Handle>` for all
of its cross-thread needs instead of `Arc<Shared>`.

The effect of this change is that the multi-thread scheduler only has a
single `Arc` type, which includes the driver handles, keeping all
"shared state" together.
2022-09-16 19:57:45 -07:00
Carl Lerche 2effa7ff8a rt: update CurrentThread to use its own Handle (#5023)
This is the next step in the internal runtime refactoring. This patch
updates `CurrentThread` to use `Arc<Handle>` for all of its cross-thread
needs instead of `Arc<Shared>`.

The effect of this change is that the current-thread scheduler only has
a single `Arc` type, which includes the driver handles, keeping all
"shared state" together.
2022-09-16 17:34:09 -07:00
Carl Lerche ebeb78ed40 rt: split internal runtime::Handle concerns (#5022)
The `runtime::Handle` struct is part of the public API but is also used
internally. This has created a bit of tension. An earlier patch made
defined Handle as a private struct in some cases when `rt` is not
enabled.

This patch splits out internal handle concerns into a new
`scheduler::Handle` type, which will only be internal. This also defines
a `Handle` type for each scheduler variant. Eventually, the
per-scheduler `Handle` types will replace the per-scheduler `Spawner`
types, but more work is needed before we can make that change.
2022-09-16 14:05:09 -07:00
Hayden Stainsby b5709baa91 rt: add rng_seed option to runtime::Builder (#4910)
The `tokio::select!` macro polls branches in a random order. While this
is desirable in production, for testing purposes a more deterministic
approach can be useul.

This change adds an additional parameter `rng_seed` to the runtime
`Builder` to set the random number generator seed. This value is then
used to reset the seed on the current thread when the runtime is entered
into (restoring the previous value when the thread leaves the runtime). All
threads created explicitly by the runtime also have a seed set as the
runtime is built. Each thread is set with a seed from a deterministic
sequence.

This guarantees that calls to the `tokio::select!` macro which are
performed in the same order on the same thread will poll branches in the
same order.

Additionally, the peer chosen to attempt to steal work from also uses a
deterministic sequence if `rng_seed` is set.

Both the builder parameter as well as the `RngSeed` struct are marked
unstable initially.
2022-09-16 17:41:09 +02:00
Carl Lerche 9e02759779 rt: create driver::Handle struct (#5018)
Move all individual driver handles into a single `driver::Handle`
struct.
2022-09-15 16:31:55 -07:00
Carl Lerche 198e2d8e79 rt: rename internal runtime::Kind to Scheduler (#5017)
The `runtime::Kind` enum doesn't really represent the runtime flavor,
but is an enumeration of the different scheduler types. This patch
renames the enum to reflect this.

At a later time, it is likely the `Scheduler` enum will be moved to
`tokio::runtime::scheduler`, but that is punted to a later PR.

This rename is to make space for other enums
2022-09-15 15:10:08 -07:00
Carl Lerche 57e08e7147 chore: remove println from tests (#5015)
This patch removes println statements from tests. Some of these were
used to test that types implement `fmt::Debug`. These println statements
have been replaced with an equivalent test that does not output to
STDOUT. The rest of the println statements are most likely left over
from debugging sessions.
2022-09-14 18:43:40 -07:00
Carl Lerche 98e642d234 rt: remove driver drop implementations (#5014)
Currently, drivers are responsible for clean up when they are dropped.
This is possible today because each driver struct holds a reference to
its internal handle.

As part of an effort to decouple drivers from their handles, this patch
removes the drop implementations for the time and IO driver in favor of
having the scheduler explicitly call `shutdown()` as part of its
shutdown process. The scheduler will hold a reference to both the driver
and the driver handles, so in the future, it will be able to pass in the
driver handles as part of the shutdown process.
2022-09-14 15:47:41 -07:00
Carl Lerche 3f379abda4 rt: remove unparker from time driver (#5013)
Currently, the various resource drivers use a layered approach where
each driver contains the next one. When the scheduler calls park on the
top-most driver, it does work then calls park on the inner driver it
holds. The handles do the same with unparking.

This patch is a step towards refactoring the runtime to move away from
the nested approach towards keeping all drivers and handles together in
a single runtime driver/handle. The unparker is removed from the time
handle and placed in the runtime handle and is passed into the time
driver as needed.
2022-09-14 15:38:42 -07:00
Carl Lerche 588408c060 rt: update TimerEntry to use runtime::Handle
The `TimerEntry` struct is the internal integration point for public
time APIs (`sleep`, `interval`, ...) with the time driver. Currently,
`TimerEntry` holds an ref-counted reference to the time driver handle.

This patch replaces the reference to the time driver handle with a
reference to the runtime handle. This is part of a larger effort to
consolate internal handles across the runtime.
2022-09-14 15:38:42 -07:00
Taiki Endo ac1ae2cfbc ci: use latest Valgrind (#4367) 2022-09-14 21:49:32 +09:00
Carl Lerche 56ffea09e5 rt: store driver handles next to scheduler handle (#5008)
In an earlier PR (#4629), driver handles were moved into the scheduler
handle (`Spawner`). This was done to let the multi-threaded scheduler
have direct access to the thread pool spawner.

However, we are now working on a greater decoupling of the runtime
internals. All drivers and schedulers will be peers, stored in a single
thread-local variable, and the scheduler will be passed the full
runtime::Handle. This will achieve the original goal of giving the
scheduler access to the thread-pool while also (hopefully) simplifying
other aspects of the code.
2022-09-13 12:40:46 -07:00
Taiki Endo b891714bdb ci: use --feature-powerset --depth 2 in features check (#5007)
As has been pointed out a few times in the past (e.g., #4036 (comment)), each-feature 
is not sufficient for features check.

Ideally, we'd like to check all combinations of features, but there are too many
combinations. So limit the max number of simultaneous feature flags to 2 by --depth
option. I think this should be sufficient in most cases as @carllerche said in
taiki-e/cargo-hack#58.
2022-09-13 11:05:38 -07:00
Jernej Kos 0fddb765d4 ci: add build test for x86_64-fortanix-unknown-sgx target (#5001) 2022-09-13 15:12:35 +02:00
Alice Ryhl 29e3584c4d ci: don't auto-cancel CI on old commits on master (#5006) 2022-09-13 13:13:27 +02:00
Alice Ryhl 0d68bef7f7 Merge 'tokio-1.21.1' into 'master' 2022-09-13 11:43:54 +02:00
Alice Ryhl dea1cd4995 chore: prepare Tokio v1.21.1 (#5003) 2022-09-13 11:20:59 +02:00
Alice Ryhl e4cbc70279 task: ignore failure to set TLS in LocalSet Drop (#4976) 2022-09-13 08:51:04 +02:00
Alice Ryhl 97e981e797 net: fix dependency resolution for socket2 (#5000) 2022-09-13 08:50:30 +02:00
Carl Lerche 3a4f18b93b rt: remove internal runtime::ToHandle trait (#5002)
The internal `runtime::ToHandle` trait is no longer needed as the
runtime handle is used everywhere now.
2022-09-12 16:18:17 -07:00
Yotam Ofek 1c823093cb codec: fix LengthDelimitedCodec buffer over-reservation (#4997) 2022-09-11 15:58:51 +02:00
Hayden Stainsby 0b1f640308 io: remove reference to missing functions from Registration docs (#4995)
The docs for `Registration::new_with_interest_and_handle` (internal
function) included a reference to two old functions `new_with_interest`
and `new` on the same struct. These functions no longer exist, which
could be confusing.

Since there is currently only a single constructor function on
`Registration`, the misleading text has simply been removed.
2022-09-09 20:36:42 +02:00
Carl Lerche d7b3b33c9c rt: move spawn_blocking methods to blocking mod (#4994)
A few spawn_blocking methods were implemented on a Handle struct that is
intended to hold all runtime driver handles. These methods make more
sense in the blocking module.
2022-09-08 13:38:20 -07:00
Carl Lerche 71b29b9409 rt: remove Handle reference from time driver (#4993)
A step towards the goal of consolidating thread-local variables, this
patch removes the `time::Handle` reference from the time driver struct.
The reference is moved a level up and passed into methods that need it.

The end goal is to have a single `Driver` struct that holds each
sub-driver and a single `Handle` ref-counted struct that holds all the
misc handles. Further work on the time driver is blocked by some other
refactoring that will happen in follow-up patches.
2022-09-08 11:42:08 -07:00
Piotr 3966acf966 io: rewrite immediate_exit_on_error test to use io::Mock (#4984) 2022-09-08 11:39:06 +02:00
Alice Ryhl dfdb550cd4 chore: prepare tokio-util 0.7.4 (#4987) 2022-09-08 10:34:23 +02:00
Carl Lerche 99aa8d12b7 rt: rm internal Park,Unpark traits (#4991)
Years ago, Tokio was organized as a cluster of separate crates. This
architecture required a trait to represent "park the thread and do
work.". When all crates were combined into a single crate, the `Park`
and `Unpark` traits remained as internal details.

This patch removes these traits as they are no longer needed. This is in
service of a future refactor that will decouple the various resource
drivers and store them in a single struct instead of nesting them.
However, in the mean time, removing the Park/Unpark traits adds a bit of
messy code to make the conditional compilation work. This code will
(hopefully) be short-lived.
2022-09-07 18:39:45 -07:00
Carl Lerche 2ad347465e rt: minor time driver refactors (#4989)
This patch makes some minor refactors. It renames `ClockTime` to
`TimeSource` since that is how all variables refer to it. It also moves
the type into a new file.

Finally, it moves the `unpark` handle out of the mutex as it does not
need to be there. Note, the call to `unpark` is still called while the
mutex is held, so there is no functional change. Moving it out of the
mutex is in preparation for moving the unpark handle completely out of
the time driver.
2022-09-07 13:24:02 -07:00
Alex Rudy 291fce8de3 io: add error handling example to StreamReader (#4975) 2022-09-07 13:58:06 +00:00
Adam Chalmers 0267516214 net: fix links in UnixStream docs (#4985) 2022-09-07 08:40:55 +00:00
Carl Lerche bbfd34f6a3 rt: move time driver into runtime module (#4983)
This patch moves the time driver into the runtime module. The time driver
is a runtime concern and is only used by the runtime. Moving the drivers
is the first step to cleaning up some Tokio internals. There will be
follow-up patches that integrate the drivers and other runtime concerns
more closely.

This is an internal refactor and should not impact any public APIs.
2022-09-06 14:12:09 -07:00
Alice Ryhl 116fa7c614 task: introduce RcCell helper (#4977) 2022-09-06 13:40:07 +02:00
Hsiang-Cheng Yang 1fd7f82468 task: fix a doc typo in LocalKey::sync_scope (#4971) 2022-09-03 13:57:18 +00:00
Noah Kennedy c2612b446f io: reduce syscalls in poll_write (#4970)
This applies the same optimization made in #4840 to writes.
2022-09-02 15:23:17 -05:00
Alice Ryhl 50795e652e chore: prepare Tokio v1.21.0 (#4967) 2022-09-02 13:51:31 +02:00
Alice Ryhl a6a95bb4a6 wasm: add documentation for wasm support (#4966) 2022-09-02 11:39:38 +02:00
Alice Ryhl ce5d2a466f task: fix some doc and test things related to stabilizing JoinSet (#4965) 2022-09-01 21:39:20 +00:00
Alice Ryhl e5467ca767 tokio: increase LTS duration to one year (#4964) 2022-09-01 21:30:51 +00:00
Jan Behrens 431ec68f93 sync: doc of watch::Sender::send improved (#4959)
Current documentation of `sync::watch::Sender::send` may be intepreted
as the method failing if at some point in past the channel has been
closed because every receiver has been dropped. This isn't true,
however, as the channel could have been reopened by using
`sync::watch::Sender::subscribe`.

This fix clarifies the behavior. Moreover, it is noted that on failure,
the value isn't made available to future subscribers (but returned as
part of the `SendError`).

Fixes #4957.
2022-09-01 21:11:01 +02:00
Alice Ryhl f207e1afe4 tokio: make 1.20.x an LTS release (#4962) 2022-09-01 21:08:31 +02:00
Alice RyhlandTaiki Endo d3cae06b5e wasm: use thread::sleep on non-wasi wasm too (#4963)
Co-authored-by: Taiki Endo <[email protected]>
2022-09-01 16:52:56 +02:00
Alice Ryhl 01ebb0aa29 task: fix warning (#4960) 2022-08-31 15:42:30 +02:00
Jon Kelley adc774bc4f Feature: Add more windows signal handlers (#4924) 2022-08-31 06:29:31 +00:00
TennyZhuang 5a2bc850af task: fix incorrect signature in Builder::spawn_on (#4953) 2022-08-30 09:23:53 +00:00
Vladimir ba93b28033 signal: make SignalKind methods const (#4956) 2022-08-29 19:47:55 +00:00
Clint Frederickson 505cc0901d time: add a comment to Interval::tick example (#4951) 2022-08-27 18:02:56 +00:00
Carl Lerche a3411a412c rt, chore: rename internal scheduler types (#4945)
For historical reasons, the current-thread runtime's scheduler was named
BasicScheduler and the multi-thread runtime's scheduler were named
ThreadPool. This patch renames the schedulers to mirror the runtime
names to increase consistency. This patch also moves the scheduler
implementations into a new `runtime::scheduler` module.
2022-08-26 09:47:19 -07:00
Carl Lerche 218f2629ff rt: move I/O driver into runtime module (#4942)
This patch moves the I/O driver into the runtime module. The I/O driver
is a runtime concern and is only used by the runtime. Moving the driver
is the first step to cleaning up some Tokio internals. There will be
follow-up patches that integrate the I/O driver and other runtime concerns
more closely.

Because `Interest` and `Ready` are public APIs, they were moved to the
top-level `io` module instead of moving the types to `runtime`.

This is an internal refactor and should not impact any public APIs.
2022-08-25 12:58:57 -07:00
Isaac Sikkema a66884a2fb net: add documentation to try_read() for zero-length buffers (#4937) 2022-08-25 09:33:25 +00:00
Carl Lerche b023522a37 rt: add unstable option to disable the LIFO slot (#4936)
The multi-threaded scheduler includes a per-worker LIFO slot to
store the last scheduled task. This can improve certain usage patterns,
especially message passing between tasks. However, this LIFO slot is not
currently stealable.

Eventually, the LIFO slot **will** become stealable. However, as a
stop-gap, this unstable option lets users disable the LIFO task when
doing so improves their application's overall performance.

Refs: #4941
2022-08-24 12:48:30 -07:00
imlk 733931d85f io: add SyncIoBridge::shutdown() (#4938) 2022-08-24 12:18:53 +00:00
Carl Lerche df28ac092f rt: extract basic_scheduler::Config (#4935) 2022-08-24 13:49:30 +02:00
John DiSanti d720770b07 ci: add cargo-check-external-types check (#4914) 2022-08-24 13:35:32 +02:00
Hayden Stainsby c9d444e8e0 doc: correct cargo doc command in contrib guide (#4933)
The command to build the documentation locally provided in the
Contribution Guide did not work for all crates in the project workspace.
Specifically, to build the docs for `tokio-stream` the flag `--cfg
docsrs` needs to be in the environment variable `RUSTFLAGS` in addition
to being in `RUSTDOCFLAGS`.

Additionally, there was text describing that the docs cannot be built
from the root of the workspace with a link to rust-lang/cargo#9274. That
issue has since been closed as complete and the listed commands do now
work from the root of the workspace. As such, that text has been
removed.
2022-08-24 13:33:23 +02:00
Hayden Stainsby e005b6c899 io: remove PollEvented docs reference to clear_read_ready (#4931)
The documentation for`PollEvented` had a single remaining reference to
`Registration::clear_read_ready`, which no longer exists. This change
updates the documentation to refer to `Registration::clear_readiness`
instead.
2022-08-23 08:47:59 +02:00
Clint Frederickson f5c1ff7599 chore: slight re-wording of unconstrained's module docs (#4928) 2022-08-21 14:15:18 -05:00
Noah Kennedy b67b8c1398 chore: stabilize JoinSet and AbortHandle (#4920)
Closes #4535.

This leaves the ID-related APIs unstable.
2022-08-19 17:16:11 +00:00
Linda_pp de81985762 docs: fix indent of tokio::sync::watch example code (#4922) 2022-08-18 09:12:58 -05:00
John DiSanti 4b1c4801b1 ci: upgrade to nightly-2022-07-26 and pin miri nightly (#4915) 2022-08-15 21:09:47 +00:00
weegee b3c7c9846b sync: add mpsc::Sender::max_capacity method (#4904) 2022-08-14 15:52:33 +00:00
John DiSanti d416b1d1d6 ci: upgrade nightly to nightly-2022-07-25 (#4903)
Upgrade the nightly to a version that works with all of miri,
cargo-hack, minimal-versions, and cargo-check-external-types.

This is a prerequisite for #4902.
2022-08-12 16:12:09 +00:00
Alice Ryhl 6e7a630243 docs: add changelog links to readme (#4907) 2022-08-12 15:57:53 +02:00
Alice Ryhl 16427f98c1 docs: link to GitHub discussions on "new issue" page (#4906) 2022-08-12 10:49:50 +00:00
Alice Ryhl 50b8ee99b7 ci: fix new error output from rustc 1.63.0 (#4905) 2022-08-12 08:57:30 +00:00
Alice Ryhl bdbb0ece10 task: add cancel safety docs to JoinHandle (#4901) 2022-08-11 11:17:03 +00:00
Sebastian Pütz 53e127205b sync: remove unused lifetime on SemaphorePermit impl (#4896) 2022-08-11 12:12:36 +02:00
Sebastian Pütz cd0ff7fbfe fs: change panic to error in File::start_seek (#4897) 2022-08-11 09:39:43 +00:00
Ivan Petkov d48c4370ce signal: don't register write interest on signal pipe (#4898) 2022-08-10 18:53:01 -07:00
Hayden Stainsby 9d9488db67 sync: remove broadcast channel slot level closed flag (#4867)
The broadcast channel allows multiple senders to send messages to
multiple receivers, where each receiver receives messages starting from
when it subscribes. After all senders are dropped, the receivers will
continue to receive all waiting messages in the buffer and then receive
a `Closed` error.

To mark that a channel has closed, it stores two closed flags, one on
the channel level and another in the buffer slot *after* the last used
slot (this may also be the earliest entry being kept for lagged
receivers, see #2425).

However, we don't need both closed flags, keeping the channel level
closed flag is sufficient.

Without the slot level closed flag, each receiver receives each message
until it is up to date and for that receiver the channel is empty. Then,
the actual return message is chosen depending on the channel level
closed flag; if the channel is NOT closed, then `Empty` is returned, if
the channel is closed then `Closed` is returned instead.

With the modified logic, there is no longer a need to append a closed
token to the internal buffer (by setting the slot level closed flag on
the next slot). This fixes the off by one error described in #4814,
which caused a receiver which was created after the channel was already
closed to get `Empty` from `try_recv` (or hang forever when calling
`recv`) instead of receiving `Closed`.

As a bonus, we save a single `bool` on each buffer slot.

Refs: #4814
2022-08-10 21:30:05 +02:00
Lioness100 53cf021b81 chore: fix word conjugations (#4894)
* chore: fix word tenses

* hyphenate
2022-08-10 11:50:25 -05:00
Tomio aea09478e1 io: fix typo in AsyncSeekExt::rewind docs (#4893) 2022-08-10 14:54:36 +00:00
Campbell He 2099d0bd87 net: add device and bind_device methods to TCP/UDP sockets (#4882) 2022-08-10 15:30:08 +02:00
Hayden Stainsby 255c1f95b7 doc: update clippy command in contribution guide (#4883)
The contribution guide describes the Tokio code of conduct and gives a
list of steps to follow when contributing in different ways. In the
guide to contributing a pull request, commands are listed to be run by
the contributor locally to help ensure that the PR will pass on CI.

The command to run clippy isn't the same as the one run on CI,
specifically the command doesn't check the tests. This commit changes
the command to match the one on CI, so that tests are checked by clippy
as well.
2022-08-09 23:46:21 +02:00
xxchan ff6fbc327d sync: add #[must_use] to lock guards (#4886) 2022-08-09 13:44:29 +02:00
199878e287 net: add tos and set_tos methods to TCP and UDP sockets (#4877)
Co-authored-by: Campbell He <[email protected]>
Co-authored-by: Taiki Endo <[email protected]>
2022-08-01 19:53:20 +02:00
Josh Soref 5ab6aaf3cd ci: scope workflows (#4857)
Signed-off-by: Josh Soref <[email protected]>
2022-07-30 13:55:53 +02:00
b-naber 1d75b57ad0 sync: implement Weak version of mpsc::Sender (#4595) 2022-07-27 15:36:52 +02:00
Alice RyhlandTaiki Endo b2ada60e70 wasm: use build script to detect wasm (#4865)
Co-authored-by: Taiki Endo <[email protected]>
2022-07-26 11:26:54 +00:00
Alice Ryhl 0dc62da21b chore: use target_family wasm instead of target_arch wasm32 (#4864) 2022-07-26 07:47:39 +00:00
Noah KennedyandCarl Lerche 28ce4eeab2 io: reduce syscalls in poll_read (#4840)
As the [epoll documentation points out](https://man7.org/linux/man-pages/man7/epoll.7.html), a read that only partially fills a buffer is sufficient to show that the socket buffer has been drained.

We can take advantage of this by clearing readiness in this case, which seems to significantly improve performance under certain conditions.

Co-authored-by: Carl Lerche <[email protected]>
2022-07-26 05:52:30 +00:00
Alice Ryhl ffff9e65fd chore: fix version detection for addr_of! (#4863) 2022-07-25 13:46:38 +00:00
Alice Ryhl 0906351daf Merge 'master' and 'tokio-1.20.1' 2022-07-25 14:21:40 +02:00
Alice Ryhl c0746b6a30 chore: prepare Tokio v1.20.1 (#4861) 2022-07-25 14:21:00 +02:00
Alice Ryhl b673eae342 chore: fix version detection in build script (#4860) 2022-07-25 14:14:12 +02:00
Josh Soref f3e340a35b chore: fix spelling mistakes (#4858)
Signed-off-by: Josh Soref <[email protected]>
2022-07-25 07:26:01 +00:00
Ivan Petkov 94a7eaed51 Revert "tests: alter integration tests for stdio to not use a handrolled cat implementation (#4803)" (#4854)
This reverts commit d8cad13fd9.
2022-07-23 16:27:35 -07:00
Hayden Stainsby 62593be261 doc: remove incorrect panic section for Builder::worker_threads (#4849)
The documentation for the runtime `Builder::worker_threads` function
incorrectly stated that it would panic if used when constructing a
`current_thread` runtime. In truth, the call to the function has no
effect.

Since adding the described panic to the code could cause new panics in
existing code using tokio, the documentation has been modified to
describe the existing behavior.

Refs: #4773
2022-07-23 19:44:00 +02:00
Ivan Petkov 1578575db8 process: use blocking threadpool for child stdio I/O (#4824) 2022-07-23 10:40:04 -07:00
Hayden Stainsby 8c482a5d62 io: add track_caller caller to no-rt io driver (#4852)
This change adds a case that was missing from the original PR, #4793.

The `io::driver::Handle::current` function was only covered by
`#[track_caller]` in the case that the `rt` feature  is enabled, however
it was missing in the case that the `rt` feture isn't enabled (in which
case a panic would be more common).

This particular case cannot be tested in the tokio tests as they always
run with all features enabled.

Refs: #4413
2022-07-21 15:25:42 +00:00
Hayden Stainsby 5288e1e144 task: add track_caller to public APIs (#4848)
Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds `#[track_caller]` to all the public APIs in the task
module of the tokio crate where the documentation describes how the
function may panic due to incorrect context or inputs.

In cases where `#[track_caller]` does not work, it has been left out.
For example, it currently does not work on async functions, blocks, or
closures. So any call stack that passes through one of these before
reaching the actual panic is not able to show the calling site outside
of tokio as the panic location.

The following functions have call stacks that pass through closures:
* `task::block_in_place`
* `task::local::spawn_local`

Tests are included to cover each potentially panicking function.

The following functions already had `#[track_caller]` applied everywhere
it was needed and only tests have been added:
* `task::spawn`
* `task::LocalKey::sync_scope`

Refs: #4413
2022-07-20 23:17:41 +02:00
Alice Ryhl 56be5286ee ci: update required ci steps (#4846) 2022-07-20 14:05:23 +02:00
dwattttt 21900bd42b net: add security flags to named pipe ServerOptions (#4845) 2022-07-20 11:13:39 +00:00
Alice Ryhl 228d4fce99 runtime: move owned field to Trailer (#4843) 2022-07-19 20:28:20 +02:00
Hayden Stainsby cbdba8bd32 net: add track_caller to public APIs (#4805)
Functions that may panic can be annotated with #[track_caller] so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds #[track_caller] to all the non-unstable public net APIs
in the main tokio crate where the documentation describes how the
function may panic due to incorrect context or inputs.  Not all panic
cases can have #[track_caller] applied fully as the callstack passes
through a closure which isn't yet supported by the annotation (e.g. net
functions called from outside a tokio runtime).

Additionally, the documentation was updated to indicate additional cases
in which the public net functions may panic (the same as the io
functions).

Tests are included to cover each potentially panicking function.

Refs: #4413
2022-07-18 20:57:45 +00:00
Alice Ryhl 6f048ca954 tokio: avoid temporary references in linked_list::Link impls (#4841) 2022-07-18 22:47:17 +02:00
Arnav Singh 922fc91408 task: propagate attributes on task-locals (#4837) 2022-07-14 11:32:28 +02:00
Noah Kennedy 5cf22e48c5 chore: allow miri to use latest nightly once again (#4833)
This reverts [#4825], as miri seems to be working again on the latest nightly.

I had originally thought it was this issue with rustup which was to blame, but this seems to be wrong: https://github.com/rust-lang/rustup/issues/3031

[#4825]: https://github.com/tokio-rs/tokio/pull/4825
2022-07-13 11:35:28 -05:00
gftea 14fca343d5 task: add LocalSet::enter (#4736) (#4765) 2022-07-13 18:10:09 +02:00
Colin Walters 8e20cfb9ef task: expand on cancellation of spawn_blocking (#4811)
I was looking at these docs again and I was thinking the
"cannot be cancelled" is misleading; let's talk about approaches
to do so.
2022-07-13 16:41:13 +02:00
Alice Ryhl d7b074eca3 Merge branch 'tokio-1.20.x' into 'master' 2022-07-13 08:48:27 +02:00
Ivan Petkov 3b6c74a40a Make task::Builder::spawn* methods fallible (#4823) 2022-07-12 15:56:33 -07:00
Noah Kennedy b343767725 chore: prepare Tokio v1.20.0 (#4830) 2022-07-12 22:03:44 +00:00
Eric Zhang de686b5355 runtime: fix typo in shutdown_background docs (#4829) 2022-07-12 20:51:28 +00:00
Richard Zak 6d3f92dddc wasm: initial support for wasm32-wasi target (#4716)
This adds initial, unstable, support for the wasm32-wasi target. Not all of Tokio's
features are supported yet as WASI's non-blocking APIs are still limited.

Refs: tokio-rs/tokio#4827
2022-07-12 13:20:26 -07:00
Noah Kennedy be620e913d chore: fix ci by hard-coding nightly version for miri (#4825)
It would seem that the latest nightly is having issues, so I went with the one from yesterday (2022-7-10).
2022-07-12 02:14:27 +00:00
Carl Lerche ad942de2b7 chore: add a regression test for WASI (#4822)
Currently, we only have WASM regression tests that run without WASI.
However, rust provides a WASI specific target which enables code to
special case WASI. This PR adds a basic test to cover that case.

This is an initial addition to help land tokio-rs/tokio#4716.
2022-07-11 12:06:40 -07:00
Hayden Stainsby 4daeea8cad sync: add track_caller to public APIs (#4808)
Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds `#[track_caller]` to all the public APIs in the sync
module of the tokio crate where the documentation describes how the
function may panic due to incorrect context or inputs.

In cases where `#[track_caller]` does not work, it has been left out.
For example, it currently does not work on async functions, blocks, or
closures. So any call stack that passes through one of these before
reaching the actual panic is not able to show the calling site outside
of tokio as the panic location.

The following functions have call stacks that pass through closures:
* `sync::watch::Sender::send_modify`
* `sync::watch::Sender::send_if_modified`

Additionally, in the above functions it is a panic inside the supplied
closure which causes the function to panic, and so showing the location
of the panic itself is desirable.

The following functions are async:
* `sync::mpsc::bounded::Sender::send_timeout`

Tests are included to cover each potentially panicking function.

Refs: #4413
2022-07-06 12:53:52 +02:00
Hayden Stainsby 18efef7d3b signal: add track_caller to public APIs (#4806)
Functions that may panic can be annotated with #[track_caller] so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds #[track_caller] to the signal() function which is the
only function in the signal public API which can panic. Documentation
was added to this function to indicate that it may panic.

Not all panic cases can have #[track_caller] applied fully as the
callstack passes through a closure which isn't yet supported by the
annotation (e.g. signal() called from outside a tokio runtime).

Tests are included to cover the case where signal() is called from a
runtime without IO enabled.

Refs: #4413
2022-07-06 12:16:12 +02:00
Noah Kennedy d8cad13fd9 tests: alter integration tests for stdio to not use a handrolled cat implementation (#4803)
This fixes #4801, where, as a result of https://github.com/rust-lang/rust/pull/95469, our implementation of cat used for this test no longer works, as stdio functions on windows now can abort the process if the pipe is set to nonblocking mode.

Unfortunately in windows, setting one end of the pipe to be nonblocking makes the whole thing nonblocking, so when, in tokio::process we set the child pipes to nonblocking mode, it causes serious problems for any rust program at the other end.

Fixing this issue is for another day, but fixing the tests is for today.
2022-07-01 22:32:15 -05:00
Arnaud Gourlay 8ed06ef825 chore: fix typo (#4798) 2022-06-30 18:35:49 +00:00
Alice RyhlandKitsu e6020c0fed task: various small improvements to LocalKey (#4795)
Co-authored-by: Kitsu <[email protected]>
2022-06-30 10:08:41 +00:00
Alphyr 7f92bce39f tokio: use const initialized thread locals where possible (#4677) 2022-06-29 09:32:14 +00:00
Uwe Klotz 7ed2737de2 sync: Add has_changed method to watch::Ref (#4758) 2022-06-29 09:20:25 +00:00
Alice Ryhl 79d802450b chore: disable caching for cross jobs (#4794)
CI is running into https://github.com/cross-rs/cross/issues/724, which
should be fixed if we clear the cache.
2022-06-29 10:46:23 +02:00
Alice Ryhl 45f24f1b86 sync: add warning for watch in non-Send futures (#4741) 2022-06-28 23:01:35 +02:00
Hayden Stainsby b51aa8f6f9 io: add track_caller to public APIs (#4793)
Functions that may panic can be annotated with #[track_caller] so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds #[track_caller] to all the non-unstable public io APIs
in the main tokio crate where the documentation describes how the
function may panic due to incorrect context or inputs.

Additionally, the documentation for `AsyncFd` was updated to indicate
that the functions `new` and `with_intent` can panic.

Tests are included to cover each potentially panicking function. The
logic to test the location of a panic (which is a little complex), has
been moved to a test support module.

Refs: #4413
2022-06-28 10:55:21 +00:00
Hayden Stainsby 3cc616877d time: add track_caller to public APIs (#4791)
Functions that may panic can be annotated with #[track_caller] so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds #[track_caller] to all the non-unstable public APIs in
tokio-util where the documentation describes how the function may panic
due to incorrect context or inputs.

In cases where `#[track_caller]` does not work, it has been left out. For
example, it currently does not work on async functions, blocks, or
closures. So any call stack that passes through one of these before
reaching the actual panic is not able to show the calling site outside
of tokio as the panic location.

The public functions that could not have `#[track_caller]` added for
this reason are:
* `time::advance`

Tests are included to cover each potentially panicking function. In the
following cases, `#[track_caller]` had already been added, and only
tests have been added:
* `time::interval`
* `time::interval_at`

Refs: #4413
2022-06-27 10:40:50 +00:00
Hayden Stainsby ad412a9833 util: add track_caller to public APIs (#4785)
* util: add track_caller to public APIs

Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds `#[track_caller]` to all the non-unstable public APIs in
tokio-util where the documentation describes how the function may panic
due to incorrect context or inputs.

In one place, an assert was added where the described behavior appeared
not to be implemented. The documentation for `DelayQueue::reserve`
states that the function will panic if the new capacity exceeds the
maximum number of entries the queue can contain. However, the function
didn't panic until a higher number caused by an allocation failure. This
is inconsistent with `DelayQueue::insert_at` which will panic if the
number of entries were to go over MAX_ENTRIES.

Tests are included to cover each potentially panicking function.

Refs: #4413

* fix tests on FreeBSD 32-bit (I hope)

Some tests were failing on FreeBSD 32-bit because the "times too far in
the future" for DelayQueue were also too far in the future for the OS.

Fixed by copying the MAX_DURATION value from where it's defined and
using it to create a duration that is just 1 more than the maximum. This
will start to break once we get close (within 2 and a bit years) of the
Epochalypse (19 Jan, 2038) - but a lot of other things are going to be
breaking on FreeBSD 32-bit by then anyway.
2022-06-27 12:31:31 +02:00
baul 55078ffec3 joinset: fix loom test without tokio_unstable (#4783) 2022-06-23 09:41:30 +02:00
Hayden Stainsby 485ca3e37c stream: add track_caller to public APIs (#4786)
Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds `#[track_caller]` to all the non-unstable public APIs
in tokio-stream (only `chunks_timeout` in `StreamExt`) where the
documentation describes how this function may panic due to incorrect
input.

A test has been included to cover the panic.

Refs: #4413
2022-06-22 17:27:23 +00:00
Hayden Stainsby 159508b916 add track_caller to public APIs (#4413) (#4772)
Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.

This change adds track caller to all the non-unstable public APIs in
Tokio core where the documentation describes how the function may panic
due to incorrect context or inputs.  Since each internal function needs
to be annotated down to the actual panic, it makes sense to start in
Tokio core functionality.

Tests are needed to ensure that all the annotations remain in place in
case internal refactoring occurs.

The test installs a panic hook to extract the file location from the
`PanicInfo` struct and clone it up to the outer scope to check that the
panic was indeed reported from within the test file.  The downside to
this approach is that the panic hook is global while set and so we need
a lot of extra functionality to effectively serialize the tests so that
only a single panic can occur at a time.

The annotation of `block_on` was removed as it did not work. It appears
to be impossible to correctly chain track caller when the call stack to
the panic passes through clojures, as the track caller annotation can
only be applied to functions. Also, the panic message itself is very
descriptive.
2022-06-22 06:31:36 +00:00
Alice Ryhl 34b8ebbe66 sync: document spurious failures in oneshot (#4777) 2022-06-19 16:07:35 +02:00
b-naber d8fb721de2 task: improve LocalPoolHandle (#4680) 2022-06-17 18:37:00 +02:00
Carl Lerche c98be229ff rt: unhandled panic config for current thread rt (#4770)
Allows the user to configure the runtime's behavior when a spawned task
panics. Currently, the panic is propagated to the JoinHandle and the
runtime resumes. This patch lets the user set the runtime to shutdown on
unhandled panic.

So far, this is only implemented for the current-thread runtime.

Refs: #4516
2022-06-16 12:54:43 -07:00
gftea 90bc5faa7e net: be more specific about winapi features (#4764) 2022-06-16 09:52:50 +00:00
Richard Zak f26ce08f37 chore: fix spelling (#4769)
Signed-off-by: Richard Zak <[email protected]>
2022-06-15 16:06:50 +00:00
NotAFile d487c1ca34 fs: warn about performance pitfall (#4762) 2022-06-15 08:22:03 +02:00
Carl Lerche f7a64538f7 rt: clean up arguments passed to basic scheduler (#4767)
Extracts the refactor from #4518.

The basic scheduler takes many configuration options as arguments to the
constructor. This cleans it up a bit by defining a `Config` struct and
using that to pass arguments to the constructor.
2022-06-14 18:35:43 -07:00
Erick Tryzelaar 8d29edca24 time: remove src/time/driver/wheel/stack.rs (#4766)
This removes tokio/src/time/driver/wheel/stack.rs. The module was
removed in #3080, but the actual file wasn't removed in it.
2022-06-13 18:14:16 +02:00
George Pyrros 89000ca1da macros: improve the documentation for #[tokio::test] (#4761) 2022-06-13 12:47:42 +00:00
David Barsky 08d49532b4 joinset: rename join_one to join_next (#4755) 2022-06-09 22:41:25 +02:00
Alice Ryhl 340c4dc3b2 chore: prepare Tokio v1.19.2 (#4754) 2022-06-06 17:38:28 +02:00
jefftt 7011a68343 time: add StreamExt::chunks_timeout (#4695) 2022-06-06 16:16:50 +02:00
Alice Ryhl c7280167db sync: fix will_wake usage in Notify (#4751) 2022-06-06 09:40:40 +02:00
Alice Ryhl bac7984417 chore: prepare Tokio v1.19.1 (#4750) 2022-06-05 13:28:42 +02:00
Alice Ryhl a7e7eca893 sync: fix panic in Notified::enable (#4747) 2022-06-05 08:43:58 +02:00
Alice Ryhl 89ccf2ad2b chore: prepare tokio-stream 0.1.9 (#4743) 2022-06-04 22:04:21 +02:00
Alice Ryhl 3f8a690c01 chore: prepare tokio-macros 1.8.0 (#4742) 2022-06-04 22:04:12 +02:00
Alice Ryhl 14c77bc434 chore: prepare tokio-util 0.7.3 (#4744) 2022-06-04 22:04:02 +02:00
Alice Ryhl 0241f1c54d chore: fix changelog typo (#4740) 2022-06-03 19:17:12 +00:00
Alice Ryhl 674d77d4ef chore: prepare Tokio v1.19.0 (#4738) 2022-06-03 20:41:16 +02:00
Max IndenandTaiki Endo 42b4c27b88 net: add take_error to TcpSocket and TcpStream (#4739)
Co-authored-by: Taiki Endo <[email protected]>
2022-06-03 19:50:52 +02:00
David KoloskiandDavid Koloski 0d4d3c34f1 sync: replace non-binding if let statements (#4735)
Found some `if let` statements that don't actually bind any variables.
This can make it somewhat confusing as to whether the pattern is binding
the value or being matched against. Switching to `matches!` and equality
comparisons allow these to be removed.

Co-authored-by: David Koloski <[email protected]>
2022-06-03 09:41:16 +02:00
Alice Ryhl 4941fbf7c4 tokio: add 1.18.x as LTS release (#4733) 2022-06-02 12:57:05 +02:00
David KoloskiandDavid Koloski cc6c2f40cb tokio: check page capacity before obtaining base pointer (#4731)
This doesn't cause any issues in practice because this is a private API
that is only used in ways that cannot trigger UB. Indexing into `slots`
is not sound until after we've asserted that the page is allocated,
since that aliases the first slot which may not be allocated. This PR
also switches to using `as_ptr` to obtain the base pointer for clarity.

Co-authored-by: David Koloski <[email protected]>
2022-06-01 21:18:06 +02:00
Aleksey Kladov 925314ba43 doc: clarify semantics of tasks outliving block_on (#4729) 2022-05-31 19:08:53 +00:00
Alice Ryhl f948cd7b33 chore: fix clippy warnings (#4727) 2022-05-31 20:26:32 +02:00
Name1e5s 83d0e7f8b3 runtime: add is_finished method for JoinHandle and AbortHandle (#4709) 2022-05-31 09:22:09 +00:00
Alice Ryhl 5fd1220c73 task: update return value of JoinSet::join_one (#4726) 2022-05-31 09:15:37 +02:00
Eliza Weisman 2bad98f879 task: add join_set::Builder for configuring JoinSet tasks (#4687) 2022-05-30 18:23:40 +02:00
Piotr Sarna 88e8c6239c task: add consume_budget for cooperative scheduling (#4498)
* task: add consume_budget for cooperative scheduling

For cpu-only computations that do not use any Tokio resources,
budgeting does not really kick in in order to yield and prevent
other tasks from starvation. The new mechanism - consume_budget,
performs a budget check, consumes a unit of it, and yields only
if the task exceeded the budget. That allows cpu-intenstive
computations to define points in the program which indicate that
some significant work was performed. It will yield only if the budget
is gone, which is a much better alternative to unconditional yielding,
which is a potentially heavy operation.

* tests: add a test case for task::consume_budget

The test case ensures that the task::consume_budget utility
actually burns budget and makes the task yield once the whole
budget is gone.
2022-05-30 09:15:54 +00:00
Alan Somers 6c0a9942ba metrics: correctly update atomics in IoDriverMetrics (#4725)
Updating an atomic variable with a load followed by a store is racy.  It
defeats the entire purpose of using atomic variables, and can result in
"lost" updates.  Instead, use fetch_add .
2022-05-30 11:14:56 +02:00
estk f6c0405084 sync: add resubscribe method to broadcast::Receiver (#4607) 2022-05-28 20:15:27 +00:00
Gus Wynn 05cbfae177 stream: add cancel-safety docs to StreamExt::next and try_next (#4715) 2022-05-27 10:28:29 +02:00
Eric Zhang 323b63fa04 time: fix example for MissedTickBehavior::Burst (#4713) 2022-05-22 21:22:03 +02:00
Rafael Bachmann 9f4959580f sync: add broadcast to list of channel types (#4712) 2022-05-22 16:46:34 +00:00
Name1e5s 50bd8ad17b chore: fix cargo audit warning by upgrading mockall (#4710) 2022-05-21 15:17:42 +02:00
Alice Ryhl 4675087090 sync: add Notified::enable (#4705) 2022-05-19 16:31:23 +00:00
Alice Ryhl a2112b47d3 chore: update macro output tests for rust 1.61.0 (#4706) 2022-05-19 15:55:11 +00:00
盏一 931a7773de io: refactor out usage of Weak in the io handle (#4656) 2022-05-19 10:24:27 +02:00
David Barsky 3fce06c2cc chore: add Netlify doc previews (#4699) 2022-05-19 09:30:06 +02:00
Aaron Turon 0b8a3c34a1 runtime: make global queue and event polling intervals configurable (#4671)
Adds knobs to the runtime builder to control the number of ticks
between polling the global task queue (fairness) and the event driver
(I/O prioritization).

Both varieties of scheduler already supported these intervals, but they
were defined by private constants. Some workloads benefit from
customizing these values.

Closes #4651
2022-05-18 11:23:53 +02:00
Alice Ryhl ddf2f5fdf6 rt: fix flaky wake_while_rt_is_dropping test (#4698) 2022-05-17 19:20:34 +02:00
Eliza Weisman 052355f064 task: add #[track_caller] to JoinSet/JoinMap (#4697)
## Motivation

Currently, the various spawning methods on `tokio::task::JoinSet` and
`tokio_util::task::JoinMap` lack `#[track_caller]` attributes, so the
`tracing` spans generated for tasks spawned on `JoinSet`s/`JoinMap`s
will have the `JoinSet` spawning method as their spawn location, rather
than the user code that called that method.

## Solution

This PR fixes that by...adding a bunch of `#[track_caller]` attributes.

## Future Work

In the future, we may also want to consider adding additional data to
the task span indicating that the task is spawned on a `JoinSet`...

Signed-off-by: Eliza Weisman <[email protected]>
2022-05-16 16:36:24 +00:00
Finomnis 454ac1c54f ci: enable ASAN in CI (#4696) 2022-05-16 16:57:03 +02:00
Alice Ryhl fa06605e45 Merge 'tokio-util-0.7.x' into master 2022-05-15 10:09:29 +02:00
Alice Ryhl 038de36132 chore: prepare tokio-util 0.7.2 (#4690) 2022-05-14 21:06:13 +02:00
Alice Ryhl 42d5a9fcd4 Merge 'tokio-util-0.6.x' into 'tokio-util-0.7.x' 2022-05-14 21:03:16 +02:00
Alice Ryhl cdb132d333 Revert "chore: disable warnings in old CI (#4691)"
This reverts commit b24df49a9d so we can
merge the CHANGELOG changes in #4691 into master.
2022-05-14 20:59:52 +02:00
Alice Ryhl 2659adf5fe chore: prepare tokio-util 0.6.10 (#4691) 2022-05-14 20:16:41 +02:00
Finomnis 0105d9971f sync: rewrite CancellationToken (#4652) 2022-05-14 20:16:36 +02:00
Alice Ryhl b24df49a9d chore: disable warnings in old CI (#4691) 2022-05-14 20:16:21 +02:00
Eliza Weisman b1557ea5b2 task: add Builder::{spawn_on, spawn_local_on, spawn_blocking_on} (#4683)
## Motivation

`task::JoinSet` currently has both `spawn`/`spawn_local` methods,
and `spawn_on`/`spawn_local_on` variants of these methods that take a
reference to a runtime `Handle` or to a `LocalSet`, and spawn tasks on
the provided runtime/`LocalSet`, rather than the current one. The
`task::Builder` type is _also_ an API type that can spawn tasks, but it
doesn't have `spawn_on` variants of its methods. It occurred to me that
it would be nice to have similar APIs on `task::Builder`.

## Solution

This branch adds `task::Builder::spawn_on`,
`task::Builder::spawn_local_on`, and `task::Builder::spawn_blocking_on`
methods, similar to those on `JoinSet`. In addition, I did some
refactoring of the internal spawning APIs --- there was a bit of
duplicated code that this PR reduces.

Signed-off-by: Eliza Weisman <[email protected]>
2022-05-14 10:44:47 -07:00
Alice Ryhl ce0e1152ad util: display JoinMap on docs.rs (#4689) 2022-05-14 18:55:26 +02:00
Alice Ryhl cf94ffc6fd windows: add features for winapi (#4663) 2022-05-14 16:44:44 +02:00
Sabrina Jewson f7346f04af util: simplify ReusableBoxFuture (#4675) 2022-05-13 23:39:13 +02:00
Finomnis addf5b5749 sync: rewrite CancellationToken (#4652) 2022-05-13 23:26:15 +02:00
Noah Kennedy 4ec6ba8b76 metrics: fix compilation with unstable, process, and rt (#4682)
Fixes #4681.
2022-05-11 19:31:37 +00:00
Sabrina Jewson 593b042f7b docs: mention that Clippy must be run with the MSRV (#4676)
## Motivation

In #4675 I learnt the hard way that Tokio uses Clippy on its MSRV. 

## Solution

Document this in the contributor's guide.
2022-05-10 17:53:43 +00:00
Alice Ryhl 71e18f7b75 Merge branch 'merge-1.18.2' into master 2022-05-08 23:37:56 +02:00
Alice Ryhl 7aa1566cde chore: prepare Tokio v1.18.2 2022-05-08 21:41:15 +02:00
Alice Ryhl 7c8e552f29 windows: add features for winapi (#4663) 2022-05-08 21:41:15 +02:00
Alice Ryhl 67074c3d44 windows: add features for winapi (#4663) 2022-05-08 20:14:28 +02:00
Alice Ryhl 938b7d6742 util: improve impl Send for ReusableBoxFuture docs (#4658) 2022-05-07 22:32:29 +02:00
Bruno 1872a425e2 macros: avoid starvation in join! and try_join! (#4624)
Fixes: #4612
2022-05-07 12:42:44 +02:00
Erick Tryzelaar c5ff797dcf udp: document and shrink some unsafe blocks (#4655)
This documents why it is safe to convert `bytes::UninitSlice` to `&mut
[MaybeUninit<u8>]`, and shrinks one of the unsafe blocks to make these
functions easier to audit.
2022-05-05 19:48:39 +00:00
Taiki Endo 2a305d2423 ci: update actions/checkout action to v3 (#4646) 2022-05-04 15:54:16 +02:00
Uwe Klotz c14566e9df watch: modify and send value conditionally (#4591)
Add a function that is more versatile than send_modify(). The result of
the passed closure indicates if the mutably borrowed value has actually
been modified or not. Receivers are only notified if the value has been
modified as indicated by the sender.

Signed-off-by: Uwe Klotz <[email protected]>
2022-05-03 06:57:10 +00:00
Alice Ryhl 148bea82ee tokio: prepare Tokio v1.18.1 (#4650) 2022-05-02 17:07:27 +02:00
Alice Ryhl dc54aec1c7 metrics: use mocked AtomicU64 in IO metrics driver (#4649) 2022-05-02 13:32:59 +02:00
Taiki Endo fa665b91a8 macros: always emit return statement (#4636)
Fixes #4635
2022-04-28 07:53:40 +09:00
Eliza Weisman 48183430fb tokio: prepare to release v1.18.0 (#4641)
# 1.18.0 (April 27, 2022)

This release adds a number of new APIs in `tokio::net`, `tokio::signal`, and
`tokio::sync`. In addition, it adds new unstable APIs to `tokio::task` (`Id`s
for uniquely identifying a task, and `AbortHandle` for remotely cancelling a
task), as well as a number of bugfixes.

### Fixed

- blocking: add missing `#[track_caller]` for `spawn_blocking` ([#4616])
- macros: fix `select` macro to process 64 branches ([#4519])
- net: fix `try_io` methods not calling Mio's `try_io` internally ([#4582])
- runtime: recover when OS fails to spawn a new thread ([#4485])

### Added

- macros: support setting a custom crate name for `#[tokio::main]` and
  `#[tokio::test]` ([#4613])
- net: add `UdpSocket::peer_addr` ([#4611])
- net: add `try_read_buf` method for named pipes ([#4626])
- signal: add `SignalKind` `Hash`/`Eq` impls and `c_int` conversion ([#4540])
- signal: add support for signals up to `SIGRTMAX` ([#4555])
- sync: add `watch::Sender::send_modify` method ([#4310])
- sync: add `broadcast::Receiver::len` method ([#4542])
- sync: add `watch::Receiver::same_channel` method ([#4581])
- sync: implement `Clone` for `RecvError` types ([#4560])

### Changed

- update `nix` to 0.24, limit features ([#4631])
- update `mio` to 0.8.1 ([#4582])
- macros: rename `tokio::select!`'s internal `util` module ([#4543])
- runtime: use `Vec::with_capacity` when building runtime ([#4553])

### Documented

- improve docs for `tokio_unstable` ([#4524])
- runtime: include more documentation for thread_pool/worker ([#4511])
- runtime: update `Handle::current`'s docs to mention `EnterGuard` ([#4567])
- time: clarify platform specific timer resolution ([#4474])
- signal: document that `Signal::recv` is cancel-safe ([#4634])
- sync: `UnboundedReceiver` close docs ([#4548])

### Unstable

The following changes only apply when building with `--cfg tokio_unstable`:

- task: add `task::Id` type ([#4630])
- task: add `AbortHandle` type for cancelling tasks in a `JoinSet` ([#4530],
  [#4640])
- task: fix missing `doc(cfg(...))` attributes for `JoinSet` ([#4531])
- task: fix broken link in `AbortHandle` RustDoc ([#4545])
- metrics: add initial IO driver metrics ([#4507])

[#4616]: https://github.com/tokio-rs/tokio/pull/4616
[#4519]: https://github.com/tokio-rs/tokio/pull/4519
[#4582]: https://github.com/tokio-rs/tokio/pull/4582
[#4485]: https://github.com/tokio-rs/tokio/pull/4485
[#4613]: https://github.com/tokio-rs/tokio/pull/4613
[#4611]: https://github.com/tokio-rs/tokio/pull/4611
[#4626]: https://github.com/tokio-rs/tokio/pull/4626
[#4540]: https://github.com/tokio-rs/tokio/pull/4540
[#4555]: https://github.com/tokio-rs/tokio/pull/4555
[#4310]: https://github.com/tokio-rs/tokio/pull/4310
[#4542]: https://github.com/tokio-rs/tokio/pull/4542
[#4581]: https://github.com/tokio-rs/tokio/pull/4581
[#4560]: https://github.com/tokio-rs/tokio/pull/4560
[#4631]: https://github.com/tokio-rs/tokio/pull/4631
[#4582]: https://github.com/tokio-rs/tokio/pull/4582
[#4543]: https://github.com/tokio-rs/tokio/pull/4543
[#4553]: https://github.com/tokio-rs/tokio/pull/4553
[#4524]: https://github.com/tokio-rs/tokio/pull/4524
[#4511]: https://github.com/tokio-rs/tokio/pull/4511
[#4567]: https://github.com/tokio-rs/tokio/pull/4567
[#4474]: https://github.com/tokio-rs/tokio/pull/4474
[#4634]: https://github.com/tokio-rs/tokio/pull/4634
[#4548]: https://github.com/tokio-rs/tokio/pull/4548
[#4630]: https://github.com/tokio-rs/tokio/pull/4630
[#4530]: https://github.com/tokio-rs/tokio/pull/4530
[#4640]: https://github.com/tokio-rs/tokio/pull/4640
[#4531]: https://github.com/tokio-rs/tokio/pull/4531
[#4545]: https://github.com/tokio-rs/tokio/pull/4545
[#4507]: https://github.com/tokio-rs/tokio/pull/4507

Signed-off-by: Eliza Weisman <[email protected]>
2022-04-27 17:08:07 +00:00
Eliza Weisman d456706528 util: implement JoinMap (#4640)
## Motivation

In many cases, it is desirable to spawn a set of tasks associated with
keys, with the ability to cancel them by key. As an example use case for
this sort of thing, see Tower's [`ReadyCache` type][1].

Now that PR #4530 adds a way of cancelling tasks in a
`tokio::task::JoinSet`, we can implement a map-like API based on the
same `IdleNotifiedSet` primitive.

## Solution

This PR adds an implementation of a `JoinMap` type to
`tokio_util::task`, using the `JoinSet` type from `tokio::task`, the
`AbortHandle` type added in #4530, and the new task IDs added in #4630.

Individual tasks can be aborted by key using the `JoinMap::abort`
method, and a set of tasks whose key match a given predicate can be
aborted using `JoinMap::abort_matching`.

When tasks complete, `JoinMap::join_one` returns their associated key
alongside the output from the spawned future, or the key and the
`JoinError` if the task did not complete successfully.

Overall, I think the way this works is pretty straightforward; much of
this PR is just API boilerplate to implement the union of applicable
APIs from `JoinSet` and `HashMap`. Unlike previous iterations on the
`JoinMap` API (e.g. #4538), this version is implemented entirely in
`tokio_util`, using only public APIs from the `tokio` crate. Currently,
the required `tokio` APIs are unstable, but implementing `JoinMap` in
`tokio-util` means we will never have to make stability commitments for
the `JoinMap` API itself.

[1]: https://github.com/tower-rs/tower/blob/master/tower/src/ready_cache/cache.rs

Signed-off-by: Eliza Weisman <[email protected]>
2022-04-26 17:25:48 +00:00
Eliza Weisman 1d3f12304e task: add task IDs (#4630)
## Motivation

PR #4538 adds a prototype implementation of a `JoinMap` API in
`tokio::task`. In [this comment][1] on that PR, @carllerche pointed out
that a much simpler `JoinMap` type could be implemented outside of
`tokio` (either in `tokio-util` or in user code) if we just modified
`JoinSet` to return a task ID type when spawning new tasks, and when
tasks complete. This seems like a better approach for the following
reasons:

* A `JoinMap`-like type need not become a permanent part of `tokio`'s
  stable API
* Task IDs seem like something that could be generally useful outside of
  a `JoinMap` implementation

## Solution

This branch adds a `tokio::task::Id` type that uniquely identifies a
task relative to all other spawned tasks. Task IDs are assigned
sequentially based on an atomic `usize` counter of spawned tasks.

In addition, I modified `JoinSet` to add a `join_with_id` method that
behaves identically to `join_one` but also returns an ID. This can be
used to implement a `JoinMap` type.

Note that because `join_with_id` must return a task ID regardless of
whether the task completes successfully or returns a `JoinError`, I've
also changed `JoinError` to carry the ID of the task that errored, and 
added a `JoinError::id` method for accessing it. Alternatively, we could
have done one of the following:

* have `join_with_id` return `Option<(Id, Result<T, JoinError>)>`, which
  would be inconsistent with the return type of `join_one` (which we've
  [already bikeshedded over once][2]...)
* have `join_with_id` return `Result<Option<(Id, T)>, (Id, JoinError)>>`,
  which just feels gross.

I thought adding the task ID to `JoinError` was the nicest option, and
is potentially useful for other stuff as well, so it's probably a good API to
have anyway.

[1]: https://github.com/tokio-rs/tokio/pull/4538#issuecomment-1065614755
[2]: https://github.com/tokio-rs/tokio/pull/4335#discussion_r773377901

Closes #4538

Signed-off-by: Eliza Weisman <[email protected]>
2022-04-25 17:31:19 +00:00
Aleksey Kladov b4d82c3e70 docs: Signal::recv is cancel-safe (#4634) 2022-04-23 09:12:24 +00:00
cui fliter 1472af5bd4 docs: fix some typos (#4632)
Signed-off-by: cuishuang <[email protected]>
2022-04-21 10:16:19 +00:00
Piepmatz d397e77c90 net: add try_read_buf for named pipes (#4626) 2022-04-21 09:50:12 +02:00
Ryan Zoeller 711d9d0156 chore: upgrade nix to 0.24, limit features (#4631)
This reduces tokio's test compile time by a few seconds.
2022-04-21 04:31:15 +00:00
Carl Lerche 911a0efa87 rt: internally split Handle into two structs (#4629)
Previously, `runtime::Handle` was a single struct composed of the
internal handles for each runtime component. This patch splits the
`Handle` struct into a `HandleInner` which contains everything
**except** the task scheduler handle. Now, `HandleInner` is passed to
the task scheduler during creation and the task scheduler is responsible
for storing it. `Handle` only  needs to hold the scheduler handle and
can access the rest of the component handles by querying the task
scheduler.

The motivation for this change is it now enables the multi-threaded
scheduler to have direct access to the blocking spawner handle.
Previously, when spawning a new thread, the multi-threaded scheduler had
to access the blocking spawner by accessing a thread-local variable.
Now, in theory, the multi-threaded scheduler can use `HandleInner`
directly. However, this change hasn't been done in this PR yet.

Also, now the `Handle` struct is much smaller.

This change is intended to make it easier for the multi-threaded
scheduler to shutdown idle threads and respawn them on demand.
2022-04-20 12:56:55 -07:00
Kezhu Wang d590a369d5 macros: custom crate name for #[tokio::main] and #[tokio::test] (#4613)
This also enables `#[crate::test(crate = "crate")]` in unit tests.

See: rust-lang/cargo#5653
Fixes: #2312
2022-04-18 11:24:27 +02:00
Name1e5s 2fe49a68a4 sync: add panic docs for tokio::sync::broadcast::channel (#4622) 2022-04-17 13:34:51 +02:00
Alan Somers c43832a7b1 ci: update FreeBSD CI image to 12.3 (#4620) 2022-04-15 11:50:40 +02:00
Dom 221bb94b9c blocking: #[track_caller] for spawn_blocking (#4616)
Annotates spawn_blocking() with #[track_caller] in order to produce the
correct tracing span spawn locations that show the caller as the spawn
point.
2022-04-13 15:27:58 +00:00
Bruno 252b0fa9d5 net: add peer_addr to UdpSocket (#4611)
The std UdpSocket has the peer_addr method which can be used to get the address of the remote peer the socket is connected to.

Fixes: #4609
2022-04-10 01:52:45 +00:00
Jedidiah Buck McCready 83477c725a time: clarify platform specific resolution in sleep function docs (#4474) 2022-04-06 15:29:44 +02:00
Stepan Koltsov 3652f71ade sync: add Clone to RecvError types (#4560) 2022-04-06 15:26:45 +02:00
ObsidianMinor b98a7e4d07 runtime: update Handle::current to mention EnterGuard (#4567)
Handle::current docs say it's not possible to call it on any non-runtime thread, but you can call it from a runtime context created by an EnterGuard. This updates the docs to mention EnterGuard as a way to avoid this panic.
2022-04-06 15:23:49 +02:00
Adam Cigánek 7d3b9d73ff stream: expose Timout (#4601) 2022-04-06 15:17:58 +02:00
Paolo Barbolini f8a6cf49cd tracing: don't require default tracing features (#4592) 2022-04-03 11:30:07 +02:00
Arash Sal Moslehian 702d6dccc9 tests: complete TODOs in uds_stream (#4587) 2022-03-28 19:58:06 +00:00
Dirkjan Ochtman a05135a4f8 chore: prepare tokio-util 0.7.1 release (#4521) 2022-03-28 14:34:11 +02:00
masa.koz 2bb97db5e1 net: make try_io methods call mio's try_io internally (#4582) 2022-03-28 09:06:47 +00:00
Matthew Ahrens a8b75dbdf4 sync: add watch::Receiver::same_channel (#4581) 2022-03-25 19:16:47 +00:00
b-naber f84c4d596a io: add StreamReader::into_inner_with_chunk (#4559) 2022-03-23 20:41:09 +01:00
Taiki Endo 121769c762 ci: run reusable_box tests with Miri (#4578) 2022-03-21 23:57:47 +09:00
Jedidiah Buck McCready 0abe825b72 time: clarify platform specific timer resolution (#4474) 2022-03-16 15:49:16 +00:00
Eliza Weisman 61e37c6c8d ci: run doctests for unstable APIs (#4562)
It turns out that the CI job for testing `tokio_unstable` features isn't
actually running doctests for `tokio_unstable`, just lib and integration
tests. This is because RustDoc is responsible for running doctests, and
it needs the unstable cfg passed to it separately from `RUSTFLAGS`.

This means that if the examples for unstable APIs are broken, CI won't
catch this, which is not great!

This commit changes the `test-unstable` CI job to pass `--cfg
tokio_unstable` in `RUSTDOCFLAGS` as well as `RUSTFLAGS`. This way,
doctests for unstable APIs should actually run.

I also fixed a typo in one of the runtime metrics doctests that was
causing a compilation error, which was caught as a result of actually
testing the unstable API docs on CI. :)

Signed-off-by: Eliza Weisman <[email protected]>
2022-03-11 20:13:51 +00:00
Eliza Weisman dee26c92dd chore: fix a bunch of annoying clippy lints (#4558)
## Motivation

Recent Clippy releases have added some new lints that trigger on some
code in Tokio. These aren't a big deal, but seeing them in my editor is
mildly annoying.

## Solution

This branch fixes the following issues flagged by Clippy:

* manual `Option::map` implementation
* use of `.map(...).flatten(...)` that could be replaced with
  `.and_then(...)`
* manual implementation of saturating arithmetic on `Duration`s
* simplify some boolean expressions in assertions (`!res.is_ok()` can be
`res.is_err()`)
* fix redundant field names in initializers
* replace an unnecessary cast to `usize` with an explicitly typed
  integer literal

Signed-off-by: Eliza Weisman <[email protected]>
2022-03-08 12:24:19 -08:00
b-naber 2f944dfa1b sync: add broadcast::Receiver::len (#4542) 2022-03-07 13:47:26 +01:00
weisbrja e8ae65a697 tokio: add support for signals up to SIGRTMAX (#4555)
The POSIX standard not only supports "reliable signals", but also
"real-time signals". This commit adds support for the latter.
2022-03-05 06:33:32 +00:00
Rafael Camargo LeiteandRafael 5b947ca2c7 runtime: include more documentation for thread_pool/worker (#4511)
Co-authored-by: Rafael <[email protected]>
2022-03-02 13:55:15 +01:00
Alisue 014be71cca stream: expose Elapsed error (#4502) 2022-03-02 13:53:21 +01:00
William ba49294bae macros: rename tokio::select!'s internal util module (#4543)
This internal module's identifier can clash with existing identifiers in library users' code and produce confusing error messages.
2022-03-02 13:37:37 +01:00
Alex Saveau fb9a01b362 runtime: use Vec::with_capacity when building runtime (#4553) 2022-03-02 12:41:43 +01:00
Quinn 6f9a586214 sync: unbounded receiver close docs (#4548) 2022-02-27 22:12:29 +01:00
Andy Barron 3dd5a0d3bb signal: add SignalKind Hash/Eq impls and c_int conversion (#4540) 2022-02-26 13:23:28 +01:00
Gus Wynn 413c812ac8 util: switch tokio-util from log to tracing (#4539) 2022-02-26 12:47:04 +01:00
Eliza Weisman ac69d37302 task: fix broken link in AbortHandle RustDoc (#4545)
## Motivation

There's a broken docs link in the docs for `AbortHandle`. Somehow this
managed to slip past CI yesterday when #4530 was merged
(https://github.com/tokio-rs/tokio/runs/5325278596?check_suite_focus=true)
but it's breaking the build now
(https://github.com/tokio-rs/tokio/runs/5337182732?check_suite_focus=true)
which seems really weird to me, but...whatever...

## Solution

This branch fixes the broken link lol.

Signed-off-by: Eliza Weisman <[email protected]>
2022-02-25 19:07:59 +00:00
Cody Casterline 4485921ba7 Improve docs for tokio_unstable. (#4524) 2022-02-25 12:36:37 -05:00
Antonin Amand 70c10bae60 runtime: recover when OS fails to spawn a new thread (#4485) 2022-02-25 12:28:56 +01:00
Eliza Weisman 8e0e56fdf2 task: add AbortHandle type for cancelling tasks in a JoinSet (#4530)
## Motivation

Before we stabilize the `JoinSet` API, we intend to add a method for
individual tasks in the `JoinSet` to be aborted. Because the
`JoinHandle`s for the tasks spawned on a `JoinSet` are owned by the
`JoinSet`, the user can no longer use them to abort tasks on the
`JoinSet`. Therefore, we need another way to cause a remote abort of a
task on a `JoinSet` without holding its `JoinHandle`.

## Solution

This branch adds a new `AbortHandle` type in `tokio::task`, which
represents the owned permission to remotely cancel a task, but _not_ to
await its output. The `AbortHandle` type holds an additional reference
to the task cell.

A crate-private method is added to `JoinHandle` that returns an
`AbortHandle` for the same task, incrementing its ref count.
`AbortHandle` provides a single method, `AbortHandle::abort(self)`, that
remotely cancels the task. Dropping an `AbortHandle` decrements the
task's ref count but does not cancel it. The `AbortHandle` type is
currently marked as unstable.

The spawning methods on `JoinSet` are modified to return an
`AbortHandle` that can be used to cancel the spawned task.

## Future Work

- Currently, the `AbortHandle` type is _only_ available in the public
API through a `JoinSet`. We could also make the
`JoinHandle::abort_handle` method public, to allow users to use the
`AbortHandle` type in other contexts. I didn't do that in this PR,
because I wanted to make the API addition as minimal as possible, but we
could make this method public later.

- Currently, `AbortHandle` is not `Clone`. We could easily make it
`Clone` by incrementing the task's ref count. Since this adds more trait
impls to the API, we may want to be cautious about this, but I see no
obvious reason we would need to remove a `Clone` implementation if one
was added...

- There's been some discussion of adding a `JoinMap` type that allows
aborting tasks by key, and manages a hash map of keys to `AbortHandle`s,
and removes the tasks from the map when they complete. This would make
aborting by key much easier, since the user wouldn't have to worry about
keeping the state of the map of abort handles and the tasks actually
active on the `JoinSet` in sync. After thinking about it a bit, I
thought this is probably best as a `tokio-util` API --- it can currently
be implemented in `tokio-util` with the APIs added in `tokio` in this
PR.

- I noticed while working on this that `JoinSet::join_one` and
`JoinSet::poll_join_one` return a cancelled `JoinError` when a task is
cancelled. I'm not sure if I love this behavior --- it seems like it
would be nicer to just skip cancelled tasks and continue polling. But,
there are currently tests that expect a cancelled `JoinError` to be
returned for each cancelled task, so I didn't want to change it in
_this_ PR. I think this is worth revisiting before stabilizing the API,
though?

Signed-off-by: Eliza Weisman <[email protected]>
2022-02-24 13:08:23 -08:00
Eliza Weisman dfac73d580 macros: update trybuild output for Rust 1.59.0 (#4536)
## Motivation

Rust error messages seem to have changed a bit in 1.59.0

## Solution

Update the `trybuild` stderr output.

This should unbreak the tests on the latest Rust (and fix CI).
2022-02-24 11:52:47 -08:00
Lucio Franco 769fb1547f tokio: Add initial io driver metrics (#4507) 2022-02-24 13:39:37 -05:00
Eliza Weisman 0b97567b49 task: fix missing doc(cfg(...)) attributes for JoinSet (#4531)
## Motivation

The `JoinSet` type is currently missing the `tokio_unstable` and
`feature = "rt"` `doc(cfg(...))` attributes, making it erroneously
appear to be available without the required feature and without unstable
features enabled. This is incorrect.

I believe this is because `doc(cfg(...))` on a re-export doesn't
actually add the required cfgs to the type itself, and the
`cfg_unstable!` is currently only guarding a re-export and module.

## Solution

This PR fixes the missing attributes.
2022-02-23 13:03:41 -08:00
Nikolai Vazquez 3f508d1622 codec: add length_field_type to LengthDelimitedCodec builder (#4508) 2022-02-23 11:46:52 +01:00
Takuya Kajiwara 503ae34cd3 util: fix import path of CancellationToken in example code (#4520) 2022-02-23 11:46:35 +01:00
Alice Ryhl ff8befbc54 ci: fix test not working on wasm (#4527) 2022-02-23 11:46:17 +01:00
Nylonicious 067ddff063 sync: add watch::Sender::send_modify method (#4310) 2022-02-22 21:19:21 +01:00
DevSabbandDevSabb e8f19e771f macros: fix select macro to process 64 branches (#4519)
Co-authored-by: DevSabb <devsabb@local>
2022-02-21 08:41:52 +01:00
Eliza Weisman 43c224ff47 chore: prepare Tokio v1.17.0 release (#4504)
# 1.17.0 (February 16, 2022)

This release updates the minimum supported Rust version (MSRV) to 1.49,
the `mio` dependency to v0.8, and the (optional) `parking_lot`
dependency to v0.12. Additionally, it contains several bug fixes, as
well as internal refactoring and performance improvements.

### Fixed

- time: prevent panicking in `sleep` with large durations ([#4495])
- time: eliminate potential panics in `Instant` arithmetic on platforms
  where `Instant::now` is not monotonic ([#4461])
- io: fix `DuplexStream` not participating in cooperative yielding
  ([#4478])
- rt: fix potential double panic when dropping a `JoinHandle` ([#4430])

### Changed

- update minimum supported Rust version to 1.49 ([#4457])
- update `parking_lot` dependency to v0.12.0 ([#4459])
- update `mio` dependency to v0.8 ([#4449])
- rt: remove an unnecessary lock in the blocking pool ([#4436])
- rt: remove an unnecessary enum in the basic scheduler ([#4462])
- time: use bit manipulation instead of modulo to improve performance
  ([#4480])
- net: use `std::future::Ready` instead of our own `Ready` future
  ([#4271])
- replace deprecated `atomic::spin_loop_hint` with `hint::spin_loop`
  ([#4491])
- fix miri failures in intrusive linked lists ([#4397])

### Documented

- io: add an example for `tokio::process::ChildStdin` ([#4479])

### Unstable

The following changes only apply when building with `--cfg
tokio_unstable`:

- task: fix missing location information in `tracing` spans generated by
  `spawn_local` ([#4483])
- task: add `JoinSet` for managing sets of tasks ([#4335])
- metrics: fix compilation error on MIPS ([#4475])
- metrics: fix compilation error on arm32v7 ([#4453])

[#4495]: https://github.com/tokio-rs/tokio/pull/4495
[#4461]: https://github.com/tokio-rs/tokio/pull/4461
[#4478]: https://github.com/tokio-rs/tokio/pull/4478
[#4430]: https://github.com/tokio-rs/tokio/pull/4430
[#4457]: https://github.com/tokio-rs/tokio/pull/4457
[#4459]: https://github.com/tokio-rs/tokio/pull/4459
[#4449]: https://github.com/tokio-rs/tokio/pull/4449
[#4462]: https://github.com/tokio-rs/tokio/pull/4462
[#4436]: https://github.com/tokio-rs/tokio/pull/4436
[#4480]: https://github.com/tokio-rs/tokio/pull/4480
[#4271]: https://github.com/tokio-rs/tokio/pull/4271
[#4491]: https://github.com/tokio-rs/tokio/pull/4491
[#4397]: https://github.com/tokio-rs/tokio/pull/4397
[#4479]: https://github.com/tokio-rs/tokio/pull/4479
[#4483]: https://github.com/tokio-rs/tokio/pull/4483
[#4335]: https://github.com/tokio-rs/tokio/pull/4335
[#4475]: https://github.com/tokio-rs/tokio/pull/4475
[#4453]: https://github.com/tokio-rs/tokio/pull/4453
2022-02-16 10:50:22 -08:00
Eliza Weisman 8758965206 task: fix unstable API documentation notes (#4503)
## Motivation

PR #4499 made the `JoinSet` API unstable, but did not add a
documentation note explaining unstable features. In general, since the
docs.rs build includes unstable APIs, it's probably worth including
these notes so that users understand what it means for an API to be
unstable.

## Solution

This branch adds a note on unstable APIs to the `JoinSet` type-level
documentation, similar to the notes for `task::Builder` and the runtime
metrics APIs.

Also, I noticed that there was a broken link to the top-level
documentation on unstable APIs in the docs for `task::Builder`, so I
fixed that as well.
2022-02-15 09:57:06 -08:00
Samuel Tardieu 28b983c4bc time: use bit manipulation instead of modulo (#4480)
time: resolve TODO

## Motivation

Existing `TODO` comment in `src/time/driver/wheel/level.rs`.

## Solution

`level_range()` always return a strictly positive power of 2. If `b` is a
strictly positive power of 2, `a - (a % b)` is equal to `a & !(b - 1)`.
2022-02-15 09:26:07 -08:00
Jonathan Johnson 0826f763e0 time: prevent panicking in sleep() with large durations (#4495) 2022-02-15 10:49:41 +01:00
Carl Lerche 37917b821d rt: make JoinSet unstable (#4499) 2022-02-15 10:37:40 +01:00
b-naber 9a3ce91ef5 util: fix waker update condition in CancellationToken (#4497)
There was a missing exclamation mark in the condition we used to test
whether we need a waker update in `check_for_cancellation`.
2022-02-14 13:18:10 -08:00
Thomas de Zeeuw 8fb15da8f8 Update to Mio v0.8
The major breaking change in Mio v0.8 is TcpSocket type being removed.

Replacing Mio's TcpSocket we switch to the socket2 library which
provides a similar type Socket, as well as SockRef, which provide all
options TcpSocket provided (and more!).

Tokio's TcpSocket type is now backed by Socket2 instead of Mio's
TcpSocket. The main pitfall here is that socket2 isn't non-blocking by
default, which Mio obviously is. As a result we have to do potentially
blocking calls more carefully, specifically we need to handle
would-block-like errors when connecting the TcpSocket ourselves.

One benefit for this change is that adding more socket options to
TcpSocket is now merely a single function call away (in most cases
anyway).
2022-02-13 16:56:18 +01:00
Taiki Endo ac0f894dd9 net: use std::future::ready instead of own Ready future (#4271) 2022-02-13 04:54:45 +09:00
Name1e5s 02141db1e1 replace spin_loop_hint with hint::spin_loop (#4491) 2022-02-12 11:47:04 -08:00
Taiki Endo 62274b0710 chore: update minimal mio requirement to 0.7.11 (#4492) 2022-02-12 10:02:46 +01:00
Dirkjan Ochtman 69f135ed60 util: bump tokio dependency to 1.6 to satisfy minimal versions (#4490) 2022-02-12 10:02:07 +01:00
coral ed187ddfb8 doc: Created a simple example for tokio::process::ChildStdin (#4479) 2022-02-11 19:38:12 -08:00
Toby Lawrence e7a0da60cd chore: prepare tokio-util 0.7.0 (#4486) 2022-02-10 12:23:58 -05:00
KestrerandToby Lawrence 9c688ecdc3 util: add lifetime parameter to ReusableBoxFuture (#3762)
Co-authored-by: Toby Lawrence <[email protected]>
2022-02-09 14:29:21 -05:00
Toby Lawrence 52fb93dce9 sync: refactored PollSender<T> to fix a subtly broken Sink<T> implementation (#4214)
Signed-off-by: Toby Lawrence <[email protected]>
2022-02-09 12:09:04 -05:00
Taiki Endo 1be8e9dfb7 miri: make miri accept our intrusive linked lists (#4397) 2022-02-09 11:11:17 +01:00
Eliza Weisman ca51f6a980 task: fix missing #[track_caller] in spawn_local (#4483)
PR #3881 factored out the spawning of local tasks on a `LocalSet` into a
function `spawn_local_inner`, so that the implementation could be shared
with the `task::Builder` API. But, that PR neglected to add a
`#[track_caller]` attribute to `spawn_local_inner`, so the `tracing`
spans for local tasks are all generated with `spawn_local_inner` as
their spawn location, rather than forwarding the actual spawn location
from the calling function.

This causes pretty useless results when using `tokio-console` with code
that spawns a number of local tasks, such as Actix
(https://reddit.com/r/rust/comments/snt5fq/can_tokioconsole_profile_actixrt/)

This commit fixes the issue by adding the missing `#[track_caller]`
attribute.
2022-02-09 10:12:06 +01:00
GongLG fd4d2b0a99 io: make duplex stream cooperative (#4470) (#4478) 2022-02-09 09:59:01 +01:00
Benjamin Saunders cf38ba627a util: remove error case from the infallible DelayQueue::poll_elapsed (#4241) 2022-02-08 21:07:33 -05:00
Sunyeop Lee 0b05ef638d codec: implement Encoder<BytesMut> for BytesCodec (#4465) 2022-02-08 09:11:24 -05:00
Alice Ryhl d6143c9566 io: improve safety comment on FillBuf (#4476) 2022-02-07 10:07:58 +01:00
Name1e5s 5690f0c32e metrics: fix build on mips (#4475) 2022-02-07 10:06:03 +01:00
Oliver Gould fc4deaa1d0 time: eliminate panics from Instant arithmetic (#4461)
`Instant::duration_since`, `Instant::elapsed`, and `Instant::sub` may
panic. This is especially dangerous when `Instant::now` travels back in
time. While this isn't supposed to happen, this behavior is highly
platform-dependent (e.g., rust-lang/rust#86470).

This change modifies the behavior of `tokio::time::Instant` to prevent
this class of panic, as proposed for `std::time::Instant` in
rust-lang/rust#89926.
2022-02-06 16:20:03 +01:00
Carl Lerche bc474f1d81 rt: remove unnecessary enum in basic_scheduler (#4462)
The enum is no longer needed. It was used previously to support multiple
kinds of control messages to the scheduler but that has been refactored
out.
2022-02-03 09:14:22 -08:00
Alice Ryhl 59579465be io: add test for take bug (#4443) 2022-02-02 16:39:16 +01:00
Alice Ryhl 1bb4d23162 task: add JoinSet for managing sets of tasks(#4335)
Adds `JoinSet` for managing multiple spawned tasks and joining them
in completion order.

Closes: #3903
2022-02-01 14:17:09 -08:00
Oliver Gould f602410227 chore: update parking_lot to v0.12.0 (#4459) 2022-01-31 14:55:40 -08:00
Carl Lerche 49fff47111 chore: increase MSRV to 1.49. (#4457)
Rust 1.49 was released on December 31, 2020, which meets our MSRV policy
of a minimum of 6 months.
2022-01-31 13:26:12 -08:00
Riley 77468ae3b0 metrics: add fetch_add for AtomicU64 (#4453) 2022-01-31 10:06:02 +01:00
Carl Lerche 2cee1db20c chore: make it easier to pin Rust versions in CI (#4448)
When backporting patches to LTS branches, we often run into CI failures due to
changes in rust. Newer rust versions add more lints, which break CI. We really
don't want to also have to backport patches that fix CI, so instead, LTS branches
should pin the stable rust version in CI (e.g. #4434).

This PR restructures the CI config files to make it a bit easier to set a specific rust
version in CI.
2022-01-30 10:07:31 -08:00
wspsxing db18e0d39d rt: reduce an unnecessary lock operation (#4436) 2022-01-28 14:01:37 -08:00
Gabriel Grubba b09899832c stream: fix disabled tests (#4441) 2022-01-28 17:30:07 +01:00
Braulio Valdivielso Martínez 111dd66f3e runtime: swallow panics in drop(JoinHandle) (#4430) 2022-01-28 17:21:03 +01:00
Alice Ryhl 91b9850505 chore: prepare Tokio v1.16.1 release (#4438) 2022-01-28 10:30:23 +01:00
Alice Ryhl 3c467056e9 io: fix take pointer check (#4437) 2022-01-28 10:04:13 +01:00
Carl Lerche afd2189eec chore: prepare Tokio v1.16 release (#4431) 2022-01-27 15:16:08 -08:00
Carl Lerche 986b88b3f1 chore: update year in LICENSE files (#4429) 2022-01-27 13:36:21 -08:00
Mark Drobnak 257053e40b util: add spawn_pinned (#3370) 2022-01-27 15:26:09 +01:00
Daniel Henry-Mantilla 5af9e0db2b sync: add blocking lock methods to RwLock (#4425) 2022-01-27 15:15:18 +01:00
Cecile Tonglet 8f77ee8609 net: add generic trait to combine UnixListener and TcpListener (#4385) 2022-01-27 15:13:37 +01:00
Ivan Petkov 2747043f6f tests: enable running wasm32-unknown-unknown tests (#4421)
* Several of tokio's features (e.g. the channel implementation) do not
  need a runtime to work, and can be compiled and used for
  wasm32-unknown-unknown targets
* This change enables running tests for the `sync` and `macros` features
  so that we can note any regressions there
2022-01-27 15:07:52 +01:00
Luiz Carlos 2a5071fc2d feat: implement Framed::map_codec (#4427) 2022-01-27 12:37:30 +01:00
Alice Ryhl 621790e165 io: fix take when using evil reader (#4428) 2022-01-27 11:45:04 +01:00
Braulio Valdivielso Martínez 7aad428994 fs: guarantee that File::write will attempt the write even if the runtime shuts down (#4316) 2022-01-25 19:46:06 +01:00
Jamie 9e38ebcaa9 task: mark JoinHandle as UnwindSafe (#4418) 2022-01-24 11:07:37 +01:00
Carl Lerche 9a57a6a7c4 chore: setup ARM CI with CircleCI (#4417) 2022-01-22 13:49:07 -08:00
Carl Lerche 24f4ee31f0 runtime: expand on runtime metrics (#4373)
This patch adds more runtime metrics. The API is still unstable.
2022-01-21 22:17:38 -08:00
Carl Lerche 4eed411519 rt: reduce no-op wakeups in the multi-threaded scheduler (#4383)
This patch reduces the number of times worker threads wake up without having
work to do in the multi-threaded scheduler. Unnecessary wake-ups are expensive
and slow down the scheduler. I have observed this change reduce no-op wakes
by up to 50%.

The multi-threaded scheduler is work-stealing. When a worker has tasks to process,
and other workers are idle (parked), these idle workers must be unparked so that
they can steal work from the busy worker. However, unparking threads is expensive,
so there is an optimization that avoids unparking a worker if there already exists
workers in a "searching" state (the worker is unparked and looking for work). This
works pretty well, but transitioning from 1 "searching" worker to 0 searching workers
introduces a race condition where a thread unpark can be lost:

* thread 1: last searching worker about to exit searching state
* thread 2: needs to unpark a thread, but skip because there is a searching worker.
* thread 1: exits searching state w/o seeing thread 2's work.

Because this should be a rare condition, Tokio solves this by always unparking a
new worker when the current worker:

* is the last searching worker
* is transitioning out of searching
* has work to process.

When the newly unparked worker wakes, if the race condition described above
happened, "thread 2"'s work will be found. Otherwise, it will just go back to sleep.

Now we come to the issue at hand. A bug incorrectly set a worker to "searching"
when the I/O driver unparked the thread. In a situation where the scheduler was
only partially under load and is able to operate with 1 active worker, the I/O driver
would unpark the thread when new I/O events are received, incorrectly transition
it to "searching", find new work generated by inbound I/O events, incorrectly
transition itself from the last searcher -> no searchers, and unpark a new thread.
This new thread would wake, find no work and go back to sleep.

Note that, when the scheduler is fully saturated, this change will make no impact
as most workers are always unparked and the optimization to avoid unparking
threads described at the top apply.
2022-01-13 15:18:32 -08:00
Carl Lerche 16a8404967 chore: fix ci to track Rust 1.58 (#4401) 2022-01-13 20:49:13 +01:00
Matthew Pomes 089eeae24b runtime: add better error message when spawning blocking threads (#4398) 2022-01-12 19:49:57 +01:00
Taiki Endo e255a265d3 ci: upgrade to new nightly (#4396) 2022-01-13 00:27:05 +09:00
Carl Lerche e951d55720 rt: refactor current-thread scheduler (take 2) (#4395)
Re-applies #4377 and fixes the bug resulting in Hyper's double panic.

Revert: #4394

Original PR:

This PR does some refactoring to the current-thread scheduler bringing it closer to the structure of the
multi-threaded scheduler. More specifically, the core scheduler data is stored in a Core struct and that
struct is passed around as a "token" indicating permission to do work. The Core structure is also stored
in the thread-local context.

This refactor is intended to support #4373, making it easier to track counters in more locations in the
current-thread scheduler.

I tried to keep commits small, but the "set Core in thread-local context" is both the biggest commit and
the key one.
2022-01-11 18:39:56 -08:00
Taiki Endo 1d698b5a90 chore: test hyper on CI (#4393) 2022-01-11 13:38:18 -08:00
Carl Lerche 867f137dc9 Revert "rt: refactor current-thread scheduler (#4377)" (#4394)
This reverts commit cc8ad367a0.
2022-01-11 11:57:14 -08:00
Carl Lerche aea26b322c Revert "Update mio to 0.8 (#4270)" and dependent changes (#4392)
This reverts commits:
 * ee0e811a36
 * 49a9dc6743
 * 0190831ec1
 * 43cdb2cb50
 * 96370ba4ce
 * a9d9bde068
2022-01-11 10:53:45 -08:00
0xd34d10cc bcb968af84 sync: add blocking_recv to oneshot::Receiver (#4334) 2022-01-10 14:42:16 +01:00
Matt Schulte cec1bc151e watch: document recursive borrow deadlock (#4360)
Under the hood, the watch channel uses a RwLock to implement reading
(borrow) and writing (send). This may cause a deadlock if a user has
concurrent borrows on the same thread. This is most likely to occur  due
to a recursive borrow.

This PR adds documentation to describe the deadlock so that future users
of the watch channel will be aware.
2022-01-10 11:41:01 +01:00
Alice Ryhl 1601de1196 process: drop pipe after child exits in wait_with_output (#4315) 2022-01-10 11:40:28 +01:00
b-naber c800deaacc util: add shrink_to_fit and compact methods to DelayQueue (#4170) 2022-01-09 12:41:30 +01:00
Jamie ac2343d984 net: add UnwindSafe impl to PollEvented (#4384) 2022-01-08 13:58:26 +01:00
Trey Smith 553cc3b194 net: document that port 0 picks a random port (#4386) 2022-01-08 13:21:11 +01:00
Eliza Weisman cb9a68eb1a examples: update tracing-subscriber to 0.3 (#4227) 2022-01-08 13:13:28 +09:00
Carl Lerche cc8ad367a0 rt: refactor current-thread scheduler (#4377)
This patch does some refactoring to the current-thread scheduler bringing it closer to the
structure of the multi-threaded scheduler. More specifically, the core scheduler data is stored
in a Core struct and that struct is passed around as a "token" indicating permission to do
work. The Core structure is also stored in the thread-local context.

This refactor is intended to support #4373, making it easier to track counters in more locations
in the current-thread scheduler.
2022-01-06 17:19:26 -08:00
Rob Ede 25e5141c36 test: fix version requirement of tokio-stream (#4376) 2022-01-04 22:01:12 +01:00
Tom Dohrmann 4a12163d7c util: add mutable reference getters for codecs to pinned Framed (#4372) 2022-01-03 22:21:43 +01:00
Elichai Turkel 12dd06336d sync: add a has_changed method to watch::Receiver (#4342) 2021-12-31 16:23:29 +01:00
Alice Ryhl c301f6d83a sync: don't inherit Send from parking_lot::*Guard (#4359) 2021-12-31 15:57:56 +01:00
Braulio Valdivielso Martínez fb35c83944 tokio-stream: add StreamExt::map_while (#4351)
Fixes #4337

Rust 1.57 stabilized the `Iterator::map_while` API. This PR adds the
same functionality to the `StreamExt` trait, to keep parity.
2021-12-31 22:53:09 +09:00
Taiki Endo 43cdb2cb50 net: add tos and set_tos methods to TCP and UDP sockets (#4366) 2021-12-31 21:19:14 +09:00
Taiki Endo 49a9dc6743 net: add buffer size methods to UdpSocket (#4363)
This adds the following methods:

- UdpSocket::set_send_buffer_size
- UdpSocket::send_buffer_size
- UdpSocket::set_recv_buffer_size
- UdpSocket::recv_buffer_size
2021-12-31 20:47:34 +09:00
Taiki Endo 96370ba4ce net: add TcpSocket::take_error (#4364) 2021-12-31 11:25:50 +01:00
Taiki Endo a9d9bde068 net: add UdpSocket::peer_addr (#4362) 2021-12-31 11:23:04 +01:00
Taiki Endo 0190831ec1 net: fix build error on master (#4361) 2021-12-31 11:21:23 +01:00
Taiki Endo ee0e811a36 Update mio to 0.8 (#4270) 2021-12-31 12:28:14 +09:00
Alice Ryhl 47feaa7a89 io: fix clippy lint in write_all (#4358) 2021-12-30 15:31:11 +01:00
Alice Ryhl dda8da75d0 stream: add StreamExt::then (#4355) 2021-12-30 15:28:13 +01:00
David Kleingeld dc1894105b codec: improve Builder::max_frame_length docs (#4352) 2021-12-28 15:08:37 +01:00
Eliza Weisman 78e0f0b42a docs: improve RustDoc for unstable features (#4331)
Currently, the docs.rs documentation for tokio is built without
--cfg tokio_unstable set. This means that unstable features are not shown in
the API docs, making them difficutl to discover. Clearly, we do want to
document the existence of unstable APIs, given that there's a section in
the lib.rs documentation listing them, so it would be better if it was
also possible to determine what APIs an unstable feature enables when
reading the RustDoc documentation.

This branch changes the docs.rs metadata to also pass --cfg tokio_unstable
when building the documentation. It turns out that it's
necessary to separately pass the cfg flag to both RustDoc and rustc,
or else the tracing dependency, which is only enabled in
target.cfg(tokio_unstable).dependencies, will be missing and the build
will fail.

In addition, I made some minor improvements to the docs for unstable
features. Some links in the task::Builder docs were broken, and the
required tokio_unstable cfg was missing from the doc(cfg(...))
attributes. Furthermore, I added a note in the top-level docs for
unstable APIs, stating that they are unstable and linking back to the
section in the crate-level docs that explains how to enable unstable
features.

Fixes #4328
2021-12-21 11:11:48 -08:00
Jinhua Tan e55f3d4398 examples: make the introduction in examples/Cargo.toml more clear (#4333) 2021-12-21 14:02:18 +01:00
Alice Ryhl 8582363b4e stats: mark stats feature unstable in lib.rs (#4327) 2021-12-18 13:40:24 +01:00
Cyborus04 c3fbaba1f9 io: replace use of transmute with pointer manipulations (#4307) 2021-12-17 20:00:24 +01:00
Fabien GaudandFabien Gaud 22e6aef6e7 net: allow to set linger on TcpSocket (#4324)
For now, this is only allowed on TcpStream. This is a problem when one
want to disable lingering (i.e. set it to Duration(0, 0)). Without being
able to set it prior to the connect call, if the connect future is
dropped it would leave sockets in a TIME_WAIT state.

Co-authored-by: Fabien Gaud <[email protected]>
2021-12-16 20:34:00 +01:00
Carl Lerche f64673580d chore: prepare Tokio v1.15.0 release (#4320)
Includes `tokio-macros` v1.7.0
2021-12-15 10:36:09 -08:00
Braulio Valdivielso Martínez 54e6693dff time: make timeout robust against budget-depleting tasks (#4314) 2021-12-15 11:59:21 +01:00
Zahari Dichev 4e3268d222 tracing: instrument more resources (#4302)
This PR adds instrumentation to more resources from the sync package. The new
instrumentation requires the `tokio_unstable` feature flag to enable.
2021-12-14 14:04:19 -08:00
Toby Lawrence 4b6bb1d9a7 chore(util): start v0.7 release cycle (#4313)
* chore(util): start v0.7 release cycle

Signed-off-by: Toby Lawrence <[email protected]>
2021-12-10 13:16:17 -05:00
Braulio Valdivielso Martínez eb1af7f29c io: make tokio::io::empty cooperative (#4300)
Reads and buffered reads from a `tokio::io::empty` were always marked
as ready. That makes sense, given that there is nothing to wait for.
However, doing repeated reads on the `empty` could stall the event
loop and prevent other tasks from making progress.

This change uses tokio's coop system to yield control back to the
executor when appropriate.

Note that the issue that originally triggered this PR is not fixed
yet, because the `timeout` function will not poll the timer after
empty::read runs out of budget. A different change will be needed to
address that.

Refs: #4291
2021-12-10 11:08:49 +01:00
Toby Lawrence 0bc9160e25 chore: update labeler.yml to drop filepath prefixes (#4308)
- update labeler.yml to drop filepath prefixes
- make sure labeler enforces labels over lifetime of PR
2021-12-09 10:40:27 -05:00
Shin Seunghun 4c571b55b1 runtime: fix typo in the task modules (#4306) 2021-12-08 13:30:52 +01:00
Naruto210 60ba634d60 time: fix typo in tokio-time document (#4304) 2021-12-07 15:49:45 +01:00
Shin Seunghun f73ed1fdba runtime: fix typo (#4303) 2021-12-07 11:07:00 +01:00
Ivan Petkov ee4b2ede83 process: add as_std() method to Command (#4295) 2021-12-03 08:51:27 +01:00
Shin Seunghun 64da914d17 time: add doc links in entry doc (#4293) 2021-12-02 15:27:46 +01:00
kenmasu d764ba5816 io: call tcp.set_nonblocking(true) in AsyncFd example. (#4292) 2021-12-02 11:01:23 +01:00
Alice Ryhl 65fb0210d5 tokio: add 1.14.x to LTS releases (#4273) 2021-11-24 09:18:50 +01:00
Axel Forsman a77b2fbab2 io: extend AsyncFdReadyGuard method lifetimes (#4267)
The implicit elided lifetimes of the `AsyncFd` references in return
types of methods on `AsyncFdReadyGuard` resolved to that of `&self`.
However that lifetime is smaller than `'a` since `self` contains an `&'a
AsyncFd` reference. This will not change so the change also does not
lessen future proofing.
2021-11-23 13:56:31 +01:00
oblique 347c0cdaba time: add Interval::reset method (#4248) 2021-11-23 13:51:07 +01:00
Shin Seunghun 2c0e5c9704 time: document missing timer panics (#4247) 2021-11-23 12:14:08 +01:00
omjadas 2a614fba0d docs: document that parking_lot is enabled by full (#4269) 2021-11-23 12:11:42 +01:00
David Pedersen 3b339024f0 stream: impl Extend for StreamMap (#4272)
## Motivation

This allows `StreamMap` to be used with [`futures::stream::StreamExt::collect`][collect].

My use case is something like this:

```rust
let stream_map: StreamMap<_, _> = things
    .into_iter()
    .map(|thing| make_stream(thing)) // iterator of futures
    .collect::<FuturesUnordered<_>>() // stream of streams
    .collect::<StreamMap<_, _>>() // combine all the inner streams into one
    .await;

async fn make_stream(thing: Thing) -> impl Stream { ... }
```

[collect]: https://docs.rs/futures/0.3.17/futures/stream/trait.StreamExt.html#method.collect

## Solution

Add `Extend` impl that delegates to the inner `Vec`.
2021-11-23 11:54:06 +01:00
Taiki Endo 1a423b3322 chore: remove doc URL from Cargo.toml (#4251)
https://doc.rust-lang.org/cargo/reference/manifest.html#the-documentation-field

> If no URL is specified in the manifest file, crates.io will
> automatically link your crate to the corresponding docs.rs page.
2021-11-23 11:53:32 +01:00
Taiki Endo a8b662f643 ci: upgrade to new nightly (#4268) 2021-11-23 19:29:57 +09:00
Taiki Endo cf3206842c chore: bump MSRV to 1.46 (#4254) 2021-11-23 12:09:24 +09:00
Taiki Endo 8943e8aeef macros: address remainging clippy::semicolon_if_nothing_returned warning (#4252) 2021-11-22 18:41:17 +09:00
Taiki Endo fe770dc509 chore: fix newly added warnings (#4253) 2021-11-22 18:40:57 +09:00
Taiki Endo 8b6542fc3e chore: update nix to 0.23 (#4255) 2021-11-22 06:13:14 +09:00
Alice Ryhl b1afd95994 sync: elaborate on cross-runtime message passing (#4240) 2021-11-17 16:02:07 +01:00
Alice Ryhl 095b5dcf93 net: add connect_std -> TcpSocket doc alias (#4219) 2021-11-16 22:22:47 +01:00
Alice Ryhl 623c09c52c chore: prepare tokio-macros 1.6.0 (#4239) 2021-11-16 09:54:07 +01:00
Eliza Weisman 884a9a4b18 chore: prepare Tokio v1.14.0 (#4234)
# 1.14.0 (November 15, 2021)

### Fixed

- macros: fix compiler errors when using `mut` patterns in `select!`
  ([#4211])
- sync: fix a data race between `oneshot::Sender::send` and awaiting a
  `oneshot::Receiver` when the oneshot has been closed ([#4226])
- sync: make `AtomicWaker` panic safe ([#3689])
- runtime: fix basic scheduler dropping tasks outside a runtime context
  ([#4213])

### Added

- stats: add `RuntimeStats::busy_duration_total` ([#4179], [#4223])

### Changed

- io: updated `copy` buffer size to match `std::io::copy` ([#4209])

### Documented

- io: rename buffer to file in doc-test ([#4230])
- sync: fix Notify example ([#4212])

[#4211]: https://github.com/tokio-rs/tokio/pull/4211
[#4226]: https://github.com/tokio-rs/tokio/pull/4226
[#3689]: https://github.com/tokio-rs/tokio/pull/3689
[#4213]: https://github.com/tokio-rs/tokio/pull/4213
[#4179]: https://github.com/tokio-rs/tokio/pull/4179
[#4223]: https://github.com/tokio-rs/tokio/pull/4223
[#4209]: https://github.com/tokio-rs/tokio/pull/4209
[#4230]: https://github.com/tokio-rs/tokio/pull/4230
[#4212]: https://github.com/tokio-rs/tokio/pull/4212
2021-11-15 16:39:09 -08:00
Eliza Weisman e0be45e49b Merge v1.13.1 (#4236)
Refs: #4235
2021-11-15 16:09:33 -08:00
Eliza Weisman 26f0938bf3 oneshot: document UnsafeCell invariants (#4229)
Depends on #4226

## Motivation

Currently, the safety invariants and synchronization strategy used in
`tokio::sync::oneshot` are not particularly obvious, especially to a new
reader. It would be nice to better document this code to make these
invariants clearer.

## Solution

This branch adds `SAFETY:` comments to the `oneshot` channel
implementation. In particular, I've focused on documenting the
invariants around when the inner `UnsafeCell` that stores the value can
be accessed by the sender and receiver sides of the channel.

I still want to take a closer look at when the waker cells can be set,
and I'd like to add more documentation there in a follow-up branch.

Signed-off-by: Eliza Weisman <[email protected]>
2021-11-15 12:46:12 -08:00
Eliza Weisman 4b78ed4d68 sync: fix racy UnsafeCell access on a closed oneshot (#4226) 2021-11-14 18:03:41 +01:00
Shin Seunghun 79d7a625d0 io: rename buffer to file in doc-test (#4230) 2021-11-13 11:31:42 +01:00
Alice Ryhl ccf855ec24 stats: only expose busy_duration_total (#4223) 2021-11-11 21:53:29 +01:00
Alice Ryhl 579f61106d ci: check for minimal versions with tokio_unstable (#4224) 2021-11-11 21:53:15 +01:00
Alice Ryhl f45320a9c0 stats: add busy_duration stats (#4179) 2021-11-08 14:59:36 -05:00
Alice Ryhl 1f8105588c runtime: drop basic scheduler tasks inside context (#4213) 2021-11-02 23:25:34 +01:00
Alice Ryhl 94ee305741 macros: fix mut patterns in select! macro (#4211) 2021-11-02 18:05:24 +01:00
Alice Ryhl 669bc4476e io: update copy buffer size (#4209) 2021-11-02 16:22:45 +01:00
Alice Ryhl 1265d0c5dc sync: fix Notify example (#4212) 2021-11-02 16:22:30 +01:00
John-John Tedro 09b770c5db sync: make AtomicWaker panic safe (#3689) 2021-11-02 13:41:36 +01:00
Alice Ryhl d1a400912e chore: prepare tokio-stream 0.1.8 (#4198) 2021-10-29 18:34:43 +02:00
539 changed files with 45554 additions and 11827 deletions
+3 -2
View File
@@ -2,6 +2,7 @@
[advisories]
ignore = [
# https://github.com/tokio-rs/tokio/issues/4177
"RUSTSEC-2020-0159",
# We depend on nix 0.22 only via mio-aio, a dev-dependency.
# https://github.com/tokio-rs/tokio/pull/4255#issuecomment-974786349
"RUSTSEC-2021-0119",
]
+25
View File
@@ -0,0 +1,25 @@
version: 2.1
jobs:
test-arm:
machine:
image: ubuntu-2004:202101-01
resource_class: arm.medium
environment:
# Change to pin rust version
RUST_STABLE: stable
steps:
- checkout
- run:
name: Install Rust
command: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o rustup.sh
chmod +x rustup.sh
./rustup.sh -y --default-toolchain $RUST_STABLE
source "$HOME"/.cargo/env
# Only run Tokio tests
- run: cargo test --all-features -p tokio
workflows:
ci:
jobs:
- test-arm
+13 -9
View File
@@ -1,6 +1,10 @@
only_if: $CIRRUS_TAG == '' && ($CIRRUS_PR != '' || $CIRRUS_BRANCH == 'master' || $CIRRUS_BRANCH =~ 'tokio-.*')
auto_cancellation: $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH !=~ 'tokio-.*'
freebsd_instance:
image: freebsd-12-2-release-amd64
image_family: freebsd-13-1
env:
RUST_STABLE: stable
RUST_NIGHTLY: nightly-2022-10-25
RUSTFLAGS: -D warnings
# Test FreeBSD in a full VM on cirrus-ci.com. Test the i686 target too, in the
@@ -10,9 +14,9 @@ env:
task:
name: FreeBSD 64-bit
setup_script:
- pkg install -y bash curl
- pkg install -y bash
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh -y --profile minimal --default-toolchain stable
- sh rustup.sh -y --profile minimal --default-toolchain $RUST_STABLE
- . $HOME/.cargo/env
- |
echo "~~~~ rustc --version ~~~~"
@@ -24,12 +28,12 @@ task:
task:
name: FreeBSD docs
env:
RUSTFLAGS: --cfg docsrs
RUSTDOCFLAGS: --cfg docsrs -Dwarnings
RUSTFLAGS: --cfg docsrs --cfg tokio_unstable
RUSTDOCFLAGS: --cfg docsrs --cfg tokio_unstable -Dwarnings
setup_script:
- pkg install -y bash curl
- pkg install -y bash
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh -y --profile minimal --default-toolchain nightly-2021-10-25
- sh rustup.sh -y --profile minimal --default-toolchain $RUST_NIGHTLY
- . $HOME/.cargo/env
- |
echo "~~~~ rustc --version ~~~~"
@@ -41,9 +45,9 @@ task:
task:
name: FreeBSD 32-bit
setup_script:
- pkg install -y bash curl
- pkg install -y bash
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh -y --profile minimal --default-toolchain stable
- sh rustup.sh -y --profile minimal --default-toolchain $RUST_STABLE
- . $HOME/.cargo/env
- rustup target add i686-unknown-freebsd
- |
+1 -1
View File
@@ -1 +1 @@
msrv = "1.45"
msrv = "1.56"
+4
View File
@@ -0,0 +1,4 @@
contact_links:
- name: Question
url: https://github.com/tokio-rs/tokio/discussions
about: Questions about Tokio should be posted as a GitHub discussion.
-16
View File
@@ -1,16 +0,0 @@
---
name: Question
about: Please use the discussions tab for questions
title: ''
labels: ''
assignees: ''
---
Please post your question as a discussion here:
https://github.com/tokio-rs/tokio/discussions
You may also be able to find help here:
https://discord.gg/tokio
https://users.rust-lang.org/
+6 -7
View File
@@ -1,9 +1,8 @@
R-loom:
- ./tokio/src/sync/*
- ./tokio/src/sync/**/*
- ./tokio-util/src/sync/*
- ./tokio-util/src/sync/**/*
- ./tokio/src/runtime/*
- ./tokio/src/runtime/**/*
- tokio/src/sync/*
- tokio/src/sync/**/*
- tokio-util/src/sync/*
- tokio-util/src/sync/**/*
- tokio/src/runtime/*
- tokio/src/runtime/**/*
+10 -2
View File
@@ -9,14 +9,22 @@ on:
schedule:
- cron: '0 2 * * *' # run at 2 AM UTC
permissions:
contents: read
jobs:
security-audit:
permissions:
checks: write # for rustsec/audit-check to create check
contents: read # for actions/checkout to fetch code
issues: write # for rustsec/audit-check to create issues
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Audit Check
uses: actions-rs/audit-check@v1
# https://github.com/rustsec/audit-check/issues/2
uses: rustsec/audit-check@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
+532 -118
View File
@@ -9,31 +9,75 @@ name: CI
env:
RUSTFLAGS: -Dwarnings
RUST_BACKTRACE: 1
nightly: nightly-2021-10-25
minrust: 1.45.2
# Change to specific Rust release to pin
rust_stable: stable
rust_nightly: nightly-2023-05-18
rust_clippy: 1.65.0
# When updating this, also update:
# - README.md
# - tokio/README.md
# - CONTRIBUTING.md
# - tokio/Cargo.toml
# - tokio-util/Cargo.toml
# - tokio-test/Cargo.toml
# - tokio-stream/Cargo.toml
rust_min: 1.56.0
defaults:
run:
shell: bash
permissions:
contents: read
jobs:
# Depends on all action sthat are required for a "successful" CI run.
# Depends on all actions that are required for a "successful" CI run.
tests-pass:
name: all systems go
runs-on: ubuntu-latest
needs:
- test
- test-parking_lot
- valgrind
- test-unstable
- miri
- cross
- asan
- cross-check
- cross-test
- no-atomic-u64
- features
- minrust
- minimal-versions
- fmt
- clippy
- docs
- valgrind
- loom-compile
- check-readme
- test-hyper
- x86_64-fortanix-unknown-sgx
- check-redox
- wasm32-unknown-unknown
- wasm32-wasi
- check-external-types
- check-fuzzing
- check-unstable-mt-counters
steps:
- run: exit 0
# Basic actions that must pass before we kick off more expensive tests.
basics:
name: basic checks
runs-on: ubuntu-latest
needs:
- clippy
- fmt
- docs
- minrust
steps:
- run: exit 0
test:
needs: basics
name: test tokio full
runs-on: ${{ matrix.os }}
strategy:
@@ -43,12 +87,16 @@ jobs:
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- uses: Swatinem/rust-cache@v2
- name: Install cargo-hack
run: cargo install cargo-hack
uses: taiki-e/install-action@cargo-hack
# Run `tokio` with `full` features. This excludes testing utilities which
# can alter the runtime behavior of Tokio.
@@ -77,19 +125,44 @@ jobs:
# bench.yml workflow runs benchmarks only on linux.
if: startsWith(matrix.os, 'ubuntu')
valgrind:
name: valgrind
test-parking_lot:
# The parking_lot crate has a feature called send_guard which changes when
# some of its types are Send. Tokio has some measures in place to prevent
# this from affecting when Tokio types are Send, and this test exists to
# ensure that those measures are working.
#
# This relies on the potentially affected Tokio type being listed in
# `tokio/tokio/tests/async_send_sync.rs`.
name: compile tests with parking lot send guards
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
- name: Enable parking_lot send_guard feature
# Inserts the line "plsend = ["parking_lot/send_guard"]" right after [features]
run: sed -i '/\[features\]/a plsend = ["parking_lot/send_guard"]' tokio/Cargo.toml
- name: Compile tests with all features enabled
run: cargo build --workspace --all-features --tests
valgrind:
name: valgrind
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
- name: Install Valgrind
run: |
sudo apt-get update -y
sudo apt-get install -y valgrind
uses: taiki-e/install-action@valgrind
# Compile tests
- name: cargo build test-mem
@@ -111,135 +184,284 @@ jobs:
test-unstable:
name: test tokio full --unstable
needs: basics
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- windows-latest
- ubuntu-latest
- macos-latest
include:
- os: windows-latest
- os: ubuntu-latest
- os: macos-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
# Run `tokio` with "unstable" cfg flag.
- name: test tokio full --cfg unstable
run: cargo test --all-features
working-directory: tokio
env:
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
# in order to run doctests for unstable features, we must also pass
# the unstable cfg to RustDoc
RUSTDOCFLAGS: --cfg tokio_unstable
test-unstable-taskdump:
name: test tokio full --unstable --taskdump
needs: basics
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
# Run `tokio` with "unstable" and "taskdump" cfg flags.
- name: test tokio full --cfg unstable --cfg taskdump
run: cargo test --all-features
working-directory: tokio
env:
RUSTFLAGS: --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings
# in order to run doctests for unstable features, we must also pass
# the unstable cfg to RustDoc
RUSTDOCFLAGS: --cfg tokio_unstable --cfg tokio_taskdump
check-unstable-mt-counters:
name: check tokio full --internal-mt-counters
needs: basics
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
# Run `tokio` with "unstable" and "taskdump" cfg flags.
- name: check tokio full --cfg unstable --cfg internal-mt-counters
run: cargo test --all-features
working-directory: tokio
env:
RUSTFLAGS: --cfg tokio_unstable --cfg tokio_internal_mt_counters -Dwarnings
# in order to run doctests for unstable features, we must also pass
# the unstable cfg to RustDoc
RUSTDOCFLAGS: --cfg tokio_unstable --cfg tokio_internal_mt_counters
miri:
name: miri
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.nightly }}
override: true
- uses: Swatinem/rust-cache@v1
- name: Install Miri
run: |
set -e
rustup component add miri
cargo miri setup
rm -rf tokio/tests
toolchain: ${{ env.rust_nightly }}
components: miri
- uses: Swatinem/rust-cache@v2
- name: miri
run: cargo miri test --features rt,rt-multi-thread,sync task
working-directory: tokio
san:
name: san
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.nightly }}
override: true
- uses: Swatinem/rust-cache@v1
- name: asan
run: cargo test --all-features --target x86_64-unknown-linux-gnu --lib -- --test-threads 1
# Many of tests in tokio/tests and doctests use #[tokio::test] or
# #[tokio::main] that calls epoll_create1 that Miri does not support.
run: cargo miri test --features full --lib --no-fail-fast
working-directory: tokio
env:
RUSTFLAGS: -Z sanitizer=address
ASAN_OPTIONS: detect_leaks=0
MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields
cross:
name: cross
asan:
name: asan
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install llvm
# Required to resolve symbols in sanitizer output
run: sudo apt-get install -y llvm
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_nightly }}
- uses: Swatinem/rust-cache@v2
- name: asan
run: cargo test --workspace --all-features --target x86_64-unknown-linux-gnu --tests -- --test-threads 1 --nocapture
env:
RUSTFLAGS: -Z sanitizer=address --cfg tokio_no_tuning_tests
# Ignore `trybuild` errors as they are irrelevant and flaky on nightly
TRYBUILD: overwrite
# Re-enable this after the next release.
#
#semver:
# name: semver
# needs: basics
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v3
# - name: Check semver
# uses: obi1kenobi/cargo-semver-checks-action@v2
# with:
# rust-toolchain: ${{ env.rust_stable }}
# release-type: minor
cross-check:
name: cross-check
needs: basics
runs-on: ubuntu-latest
strategy:
matrix:
target:
- i686-unknown-linux-gnu
- powerpc-unknown-linux-gnu
- powerpc64-unknown-linux-gnu
- mips-unknown-linux-gnu
- arm-linux-androideabi
- mipsel-unknown-linux-musl
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
toolchain: ${{ env.rust_stable }}
target: ${{ matrix.target }}
override: true
- uses: Swatinem/rust-cache@v1
- uses: actions-rs/cargo@v1
- name: Install cross
uses: taiki-e/install-action@cross
- run: cross check --workspace --all-features --target ${{ matrix.target }}
env:
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
cross-test:
name: cross-test
needs: basics
runs-on: ubuntu-latest
strategy:
matrix:
include:
- target: i686-unknown-linux-gnu
rustflags: --cfg tokio_taskdump
- target: arm-unknown-linux-gnueabihf
- target: armv7-unknown-linux-gnueabihf
- target: aarch64-unknown-linux-gnu
rustflags: --cfg tokio_taskdump
# Run a platform without AtomicU64 and no const Mutex::new
- target: arm-unknown-linux-gnueabihf
rustflags: --cfg tokio_no_const_mutex_new
steps:
- uses: actions/checkout@v3
- name: Install Rust stable
uses: dtolnay/rust-toolchain@master
with:
use-cross: true
command: check
args: --workspace --target ${{ matrix.target }}
toolchain: ${{ env.rust_stable }}
target: ${{ matrix.target }}
- name: Install cross
uses: taiki-e/install-action@cross
# First run with all features (including parking_lot)
- run: cross test -p tokio --all-features --target ${{ matrix.target }} --tests
env:
RUSTFLAGS: --cfg tokio_unstable -Dwarnings --cfg tokio_no_ipv6 --cfg tokio_no_tuning_tests ${{ matrix.rustflags }}
# Now run without parking_lot
- name: Remove `parking_lot` from `full` feature
run: sed -i '0,/parking_lot/{/parking_lot/d;}' tokio/Cargo.toml
# The `tokio_no_parking_lot` cfg is here to ensure the `sed` above does not silently break.
- run: cross test -p tokio --features full,test-util --target ${{ matrix.target }} --tests
env:
RUSTFLAGS: --cfg tokio_unstable -Dwarnings --cfg tokio_no_ipv6 --cfg tokio_no_parking_lot --cfg tokio_no_tuning_tests ${{ matrix.rustflags }}
# See https://github.com/tokio-rs/tokio/issues/5187
no-atomic-u64:
name: Test i686-unknown-linux-gnu without AtomicU64
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_nightly }}
components: rust-src
- name: Install cargo-hack
uses: taiki-e/install-action@cargo-hack
# Install linker and libraries for i686-unknown-linux-gnu
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: i686-unknown-linux-gnu
- run: cargo test -Zbuild-std --target target-specs/i686-unknown-linux-gnu.json -p tokio --all-features -- --test-threads 1 --nocapture
env:
RUSTFLAGS: --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings --cfg tokio_no_atomic_u64
# https://github.com/tokio-rs/tokio/pull/5356
# https://github.com/tokio-rs/tokio/issues/5373
- run: cargo hack build -p tokio --feature-powerset --depth 2 --keep-going
env:
RUSTFLAGS: --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings --cfg tokio_no_atomic_u64 --cfg tokio_no_const_mutex_new
- run: cargo hack build -p tokio --feature-powerset --depth 2 --keep-going
env:
RUSTFLAGS: --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings --cfg tokio_no_atomic_u64
features:
name: features
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.nightly }}
override: true
- uses: Swatinem/rust-cache@v1
toolchain: ${{ env.rust_nightly }}
target: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- name: Install cargo-hack
run: cargo install cargo-hack
- name: check --each-feature
run: cargo hack check --all --each-feature -Z avoid-dev-deps
uses: taiki-e/install-action@cargo-hack
- name: check --feature-powerset
run: cargo hack check --all --feature-powerset --depth 2 --keep-going
# Try with unstable feature flags
- name: check --each-feature --unstable
run: cargo hack check --all --each-feature -Z avoid-dev-deps
- name: check --feature-powerset --unstable
run: cargo hack check --all --feature-powerset --depth 2 --keep-going
env:
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
# Try with unstable and taskdump feature flags
- name: check --feature-powerset --unstable --taskdump
run: cargo hack check --all --feature-powerset --depth 2 --keep-going
env:
RUSTFLAGS: --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings
minrust:
name: minrust
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_min }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.minrust }}
override: true
- uses: Swatinem/rust-cache@v1
- name: "test --workspace --all-features"
toolchain: ${{ env.rust_min }}
- uses: Swatinem/rust-cache@v2
- name: "check --workspace --all-features"
run: cargo check --workspace --all-features
env:
RUSTFLAGS: "" # remove -Dwarnings
minimal-versions:
name: minimal-versions
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.nightly }}
override: true
- uses: Swatinem/rust-cache@v1
toolchain: ${{ env.rust_nightly }}
- uses: Swatinem/rust-cache@v2
- name: Install cargo-hack
run: cargo install cargo-hack
uses: taiki-e/install-action@cargo-hack
- name: "check --all-features -Z minimal-versions"
run: |
# Remove dev-dependencies from Cargo.toml to prevent the next `cargo update`
@@ -248,24 +470,34 @@ jobs:
# Update Cargo.lock to minimal version dependencies.
cargo update -Z minimal-versions
cargo hack check --all-features --ignore-private
- name: "check --all-features --unstable -Z minimal-versions"
env:
RUSTFLAGS: --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings
run: |
# Remove dev-dependencies from Cargo.toml to prevent the next `cargo update`
# from determining minimal versions based on dev-dependencies.
cargo hack --remove-dev-deps --workspace
# Update Cargo.lock to minimal version dependencies.
cargo update -Z minimal-versions
cargo hack check --all-features --ignore-private
fmt:
name: fmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- name: Install rustfmt
run: rustup component add rustfmt
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
components: rustfmt
- uses: Swatinem/rust-cache@v2
# Check fmt
- name: "rustfmt --check"
# Workaround for rust-lang/cargo#7732
run: |
if ! rustfmt --check --edition 2018 $(git ls-files '*.rs'); then
printf "Please run \`rustfmt --edition 2018 \$(git ls-files '*.rs')\` to fix rustfmt errors.\nSee CONTRIBUTING.md for more details.\n" >&2
if ! rustfmt --check --edition 2021 $(git ls-files '*.rs'); then
printf "Please run \`rustfmt --edition 2021 \$(git ls-files '*.rs')\` to fix rustfmt errors.\nSee CONTRIBUTING.md for more details.\n" >&2
exit 1
fi
@@ -273,13 +505,13 @@ jobs:
name: clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update 1.52.1 && rustup default 1.52.1
- uses: Swatinem/rust-cache@v1
- name: Install clippy
run: rustup component add clippy
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_clippy }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_clippy }}
components: clippy
- uses: Swatinem/rust-cache@v2
# Run clippy
- name: "clippy --all"
run: cargo clippy --all --tests --all-features
@@ -288,26 +520,29 @@ jobs:
name: docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.nightly }}
override: true
- uses: Swatinem/rust-cache@v1
toolchain: ${{ env.rust_nightly }}
- uses: Swatinem/rust-cache@v2
- name: "doc --lib --all-features"
run: cargo doc --lib --no-deps --all-features --document-private-items
env:
RUSTFLAGS: --cfg docsrs
RUSTDOCFLAGS: --cfg docsrs -Dwarnings
RUSTFLAGS: --cfg docsrs --cfg tokio_unstable --cfg tokio_taskdump
RUSTDOCFLAGS: --cfg docsrs --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings
loom-compile:
name: build loom tests
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
- name: build --cfg loom
run: cargo test --no-run --lib --features full
working-directory: tokio
@@ -318,10 +553,189 @@ jobs:
name: Check README
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Verify that both READMEs are identical
run: diff README.md tokio/README.md
- name: Verify that Tokio version is up to date in README
working-directory: tokio
run: grep -q "$(sed '/^version = /!d' Cargo.toml | head -n1)" README.md
test-hyper:
name: Test hyper
needs: basics
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- windows-latest
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
- name: Test hyper
run: |
set -x
git clone https://github.com/hyperium/hyper.git
cd hyper
# checkout the latest release because HEAD maybe contains breakage.
tag=$(git describe --abbrev=0 --tags)
git checkout "${tag}"
echo '[workspace]' >>Cargo.toml
echo '[patch.crates-io]' >>Cargo.toml
echo 'tokio = { path = "../tokio" }' >>Cargo.toml
echo 'tokio-util = { path = "../tokio-util" }' >>Cargo.toml
echo 'tokio-stream = { path = "../tokio-stream" }' >>Cargo.toml
echo 'tokio-test = { path = "../tokio-test" }' >>Cargo.toml
git diff
cargo test --features full
x86_64-fortanix-unknown-sgx:
name: build tokio for x86_64-fortanix-unknown-sgx
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_nightly }}
target: x86_64-fortanix-unknown-sgx
- uses: Swatinem/rust-cache@v2
# NOTE: Currently the only test we can run is to build tokio with rt and sync features.
- name: build tokio
run: cargo build --target x86_64-fortanix-unknown-sgx --features rt,sync
working-directory: tokio
check-redox:
name: build tokio for redox-os
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_nightly }}
target: x86_64-unknown-redox
- name: check tokio on redox
run: cargo check --target x86_64-unknown-redox --all-features
working-directory: tokio
wasm32-unknown-unknown:
name: test tokio for wasm32-unknown-unknown
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: test tokio
run: wasm-pack test --node -- --features "macros sync"
working-directory: tokio
wasm32-wasi:
name: wasm32-wasi
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
# Install dependencies
- name: Install cargo-hack
uses: taiki-e/install-action@cargo-hack
- name: Install wasm32-wasi target
run: rustup target add wasm32-wasi
- name: Install wasmtime
uses: taiki-e/install-action@wasmtime
- name: Install cargo-wasi
run: cargo install cargo-wasi
- name: WASI test tokio full
run: cargo test -p tokio --target wasm32-wasi --features full
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
- name: WASI test tokio-util full
run: cargo test -p tokio-util --target wasm32-wasi --features full
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
- name: WASI test tokio-stream
run: cargo test -p tokio-stream --target wasm32-wasi --features time,net,io-util,sync
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
- name: test tests-integration --features wasi-rt
# TODO: this should become: `cargo hack wasi test --each-feature`
run: cargo wasi test --test rt_yield --features wasi-rt
working-directory: tests-integration
check-external-types:
name: check-external-types (${{ matrix.os }})
needs: basics
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- windows-latest
- ubuntu-latest
rust:
# `check-external-types` requires a specific Rust nightly version. See
# the README for details: https://github.com/awslabs/cargo-check-external-types
- nightly-2023-05-31
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ matrix.rust }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2
- name: Install cargo-check-external-types
uses: taiki-e/cache-cargo-install-action@v1
with:
tool: [email protected]
- name: check-external-types
run: cargo check-external-types --all-features --config external-types.toml
working-directory: tokio
check-fuzzing:
name: check-fuzzing
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_nightly }}
- uses: Swatinem/rust-cache@v2
- name: Install cargo-fuzz
run: cargo install cargo-fuzz
- name: Check /tokio/
run: cargo fuzz check --all-features
working-directory: tokio
- name: Check /tokio-stream/
run: cargo fuzz check --all-features
working-directory: tokio-stream
+8
View File
@@ -4,10 +4,18 @@ on:
# See .github/labeler.yml file
permissions:
contents: read
jobs:
triage:
permissions:
contents: read # for actions/labeler to determine modified files
pull-requests: write # for actions/labeler to add labels to PRs
runs-on: ubuntu-latest
if: github.repository_owner == 'tokio-rs'
steps:
- uses: actions/labeler@v3
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
sync-labels: true
+28 -14
View File
@@ -10,31 +10,45 @@ name: Loom
env:
RUSTFLAGS: -Dwarnings
RUST_BACKTRACE: 1
# Change to specific Rust release to pin
rust_stable: stable
permissions:
contents: read
jobs:
loom:
name: loom
# base_ref is null when it's not a pull request
if: contains(github.event.pull_request.labels.*.name, 'R-loom') || (github.base_ref == null)
if: github.repository_owner == 'tokio-rs' && (contains(github.event.pull_request.labels.*.name, 'R-loom') || (github.base_ref == null))
runs-on: ubuntu-latest
strategy:
matrix:
scope:
- --skip loom_pool
- loom_pool::group_a
- loom_pool::group_b
- loom_pool::group_c
- loom_pool::group_d
- time::driver
include:
- scope: --skip loom_pool
max_preemptions: 2
- scope: loom_pool::group_a
max_preemptions: 2
- scope: loom_pool::group_b
max_preemptions: 2
- scope: loom_pool::group_c
max_preemptions: 2
- scope: loom_pool::group_d
max_preemptions: 2
- scope: time::driver
max_preemptions: 2
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
- name: loom ${{ matrix.scope }}
run: cargo test --lib --release --features full -- --nocapture $SCOPE
working-directory: tokio
env:
RUSTFLAGS: --cfg loom --cfg tokio_unstable -Dwarnings
LOOM_MAX_PREEMPTIONS: 2
RUSTFLAGS: --cfg loom --cfg tokio_unstable -Dwarnings -C debug-assertions
LOOM_MAX_PREEMPTIONS: ${{ matrix.max_preemptions }}
LOOM_MAX_BRANCHES: 10000
SCOPE: ${{ matrix.scope }}
+7 -11
View File
@@ -8,25 +8,21 @@ on:
paths:
- '**/Cargo.toml'
permissions:
contents: read
jobs:
security-audit:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install cargo-audit
uses: actions-rs/cargo@v1
with:
command: install
args: cargo-audit
run: cargo install cargo-audit
- name: Generate lockfile
uses: actions-rs/cargo@v1
with:
command: generate-lockfile
run: cargo generate-lockfile
- name: Audit dependencies
uses: actions-rs/cargo@v1
with:
command: audit
run: cargo audit
+18 -9
View File
@@ -5,8 +5,17 @@ on:
branches:
- master
env:
RUSTFLAGS: -Dwarnings
RUST_BACKTRACE: 1
# Change to specific Rust release to pin
rust_stable: stable
permissions:
contents: read
jobs:
stess-test:
stress-test:
name: Stress Test
runs-on: ubuntu-latest
strategy:
@@ -14,14 +23,14 @@ jobs:
stress-test:
- simple_echo_tcp
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- uses: actions/checkout@v3
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_stable }}
- uses: Swatinem/rust-cache@v2
- name: Install Valgrind
run: |
sudo apt-get update -y
sudo apt-get install -y valgrind
uses: taiki-e/install-action@valgrind
# Compiles each of the stress test examples.
- name: Compile stress test examples
@@ -29,4 +38,4 @@ jobs:
# Runs each of the examples using Valgrind. Detects leaks and displays them.
- name: Run valgrind
run: valgrind --leak-check=full --show-leak-kinds=all ./target/release/examples/${{ matrix.stress-test }}
run: valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./target/release/examples/${{ matrix.stress-test }}
+3
View File
@@ -1,2 +1,5 @@
target
Cargo.lock
.cargo/config.toml
.cargo/config
+82 -10
View File
@@ -131,29 +131,52 @@ cargo check --all-features
cargo test --all-features
```
Ideally, you should use the same version of clippy as the one used in CI
(defined by `env.rust_clippy` in [ci.yml][ci.yml]), because newer versions
might have new lints:
[ci.yml]: .github/workflows/ci.yml
<!--
When updating this, also update:
- .github/workflows/ci.yml
- README.md
- tokio/README.md
- tokio/Cargo.toml
- tokio-util/Cargo.toml
- tokio-test/Cargo.toml
- tokio-stream/Cargo.toml
-->
```
cargo +1.65.0 clippy --all --tests --all-features
```
When building documentation normally, the markers that list the features
required for various parts of Tokio are missing. To build the documentation
correctly, use this command:
```
RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features
RUSTDOCFLAGS="--cfg docsrs" RUSTFLAGS="--cfg docsrs" cargo +nightly doc --all-features
```
There is currently a [bug in cargo] that means documentation cannot be built
from the root of the workspace. If you `cd` into the `tokio` subdirectory the
command shown above will work.
To build documentation including Tokio's unstable features, it is necessary to
pass `--cfg tokio_unstable` to both RustDoc *and* rustc. To build the
documentation for unstable features, use this command:
[bug in cargo]: https://github.com/rust-lang/cargo/issues/9274
```
RUSTDOCFLAGS="--cfg docsrs --cfg tokio_unstable" RUSTFLAGS="--cfg docsrs --cfg tokio_unstable" cargo +nightly doc --all-features
```
The `cargo fmt` command does not work on the Tokio codebase. You can use the
command below instead:
```
# Mac or Linux
rustfmt --check --edition 2018 $(git ls-files '*.rs')
rustfmt --check --edition 2021 $(git ls-files '*.rs')
# Powershell
Get-ChildItem . -Filter "*.rs" -Recurse | foreach { rustfmt --check --edition 2018 $_.FullName }
Get-ChildItem . -Filter "*.rs" -Recurse | foreach { rustfmt --check --edition 2021 $_.FullName }
```
The `--check` argument prints the things that need to be fixed. If you remove
it, `rustfmt` will update your files locally instead.
@@ -165,14 +188,34 @@ LOOM_MAX_PREEMPTIONS=1 RUSTFLAGS="--cfg loom" \
cargo test --lib --release --features full -- --test-threads=1 --nocapture
```
You can run miri tests with
```
MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-tag-raw-pointers" \
cargo +nightly miri test --features full --lib
```
### Tests
If the change being proposed alters code (as opposed to only documentation for
example), it is either adding new functionality to Tokio or it is fixing
existing, broken functionality. In both of these cases, the pull request should
include one or more tests to ensure that Tokio does not regress in the future.
There are two ways to write tests: integration tests and documentation tests
(Tokio avoids unit tests as much as possible).
There are two ways to write tests: [integration tests][integration-tests]
and [documentation tests][documentation-tests].
(Tokio avoids [unit tests][unit-tests] as much as possible).
Tokio uses [conditional compilation attributes][conditional-compilation]
throughout the codebase, to modify rustc's behavior. Code marked with such
attributes can be enabled using RUSTFLAGS and RUSTDOCFLAGS environment
variables. One of the most prevalent flags passed in these variables is
the `--cfg` option. To run tests in a particular file, check first what
options #![cfg] declaration defines for that file.
For instance, to run a test marked with the 'tokio_unstable' cfg option,
you must pass this flag to the compiler when running the test.
```
$ RUSTFLAGS="--cfg tokio_unstable" cargo test -p tokio --all-features --test rt_metrics
```
#### Integration tests
@@ -183,6 +226,31 @@ utilities available to use in tests, no matter the crate being tested.
The best strategy for writing a new integration test is to look at existing
integration tests in the crate and follow the style.
#### Fuzz tests
Some of our crates include a set of fuzz tests, this will be marked by a
directory `fuzz`. It is a good idea to run fuzz tests after each change.
To get started with fuzz testing you'll need to install
[cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz).
`cargo install cargo-fuzz`
To list the available fuzzing harnesses you can run;
```bash
$ cd tokio
$ cargo fuzz list
fuzz_linked_list
````
Running a fuzz test is as simple as;
`cargo fuzz run fuzz_linked_list`
**NOTE**: Keep in mind that by default when running a fuzz test the fuzz
harness will run forever and will only exit if you `ctrl-c` or it finds
a bug.
#### Documentation tests
Ideally, every API has at least one [documentation test] that demonstrates how to
@@ -530,7 +598,7 @@ Tokio ≥1.0.0 comes with LTS guarantees:
The goal of these guarantees is to provide stability to the ecosystem.
## Mininum Supported Rust Version (MSRV)
## Minimum Supported Rust Version (MSRV)
* All Tokio ≥1.0.0 releases will support at least a 6-month old Rust
compiler release.
@@ -607,3 +675,7 @@ When releasing a new version of a crate, follow these steps:
entry for that release version into your editor and close the window.
[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog/blob/master/CHANGELOG.md
[unit-tests]: https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html
[integration-tests]: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html
[documentation-tests]: https://doc.rust-lang.org/rust-by-example/testing/doc_testing.html
[conditional-compilation]: https://doc.rust-lang.org/reference/conditional-compilation.html
+1 -1
View File
@@ -1,5 +1,5 @@
[workspace]
resolver = "2"
members = [
"tokio",
"tokio-macros",
+5
View File
@@ -0,0 +1,5 @@
[build.env]
passthrough = [
"RUSTFLAGS",
"RUST_BACKTRACE",
]
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2021 Tokio Contributors
Copyright (c) 2023 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
+47 -10
View File
@@ -56,7 +56,7 @@ Make sure you activated the full features of the tokio crate on Cargo.toml:
```toml
[dependencies]
tokio = { version = "1.13.0", features = ["full"] }
tokio = { version = "1.28.2", features = ["full"] }
```
Then, on your main.rs:
@@ -161,11 +161,46 @@ several other libraries, including:
[`mio`]: https://github.com/tokio-rs/mio
[`bytes`]: https://github.com/tokio-rs/bytes
## Changelog
The Tokio repository contains multiple crates. Each crate has its own changelog.
* `tokio` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio/CHANGELOG.md)
* `tokio-util` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-util/CHANGELOG.md)
* `tokio-stream` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-stream/CHANGELOG.md)
* `tokio-macros` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-macros/CHANGELOG.md)
* `tokio-test` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-test/CHANGELOG.md)
## Supported Rust Versions
Tokio is built against the latest stable release. The minimum supported version
is 1.45. The current Tokio version is not guaranteed to build on Rust versions
earlier than the minimum supported version.
<!--
When updating this, also update:
- .github/workflows/ci.yml
- CONTRIBUTING.md
- README.md
- tokio/README.md
- tokio/Cargo.toml
- tokio-util/Cargo.toml
- tokio-test/Cargo.toml
- tokio-stream/Cargo.toml
-->
Tokio will keep a rolling MSRV (minimum supported rust version) policy of **at
least** 6 months. When increasing the MSRV, the new Rust version must have been
released at least six months ago. The current MSRV is 1.56.0.
Note that the MSRV is not increased automatically, and only as part of a minor
release. The MSRV history for past minor releases can be found below:
* 1.27 to now - Rust 1.56
* 1.17 to 1.26 - Rust 1.49
* 1.15 to 1.16 - Rust 1.46
* 1.0 to 1.14 - Rust 1.45
Note that although we try to avoid the situation where a dependency transitively
increases the MSRV of Tokio, we do not guarantee that this does not happen.
However, every minor release will have some set of versions of dependencies that
works with the MSRV of that minor release.
## Release schedule
@@ -180,17 +215,19 @@ warrants a patch release with a fix for the bug, it will be backported and
released as a new patch release for each LTS minor version. Our current LTS
releases are:
* `1.8.x` - LTS release until February 2022.
* `1.18.x` - LTS release until June 2023. (MSRV 1.49)
* `1.20.x` - LTS release until September 2023. (MSRV 1.49)
* `1.25.x` - LTS release until March 2024. (MSRV 1.49)
Each LTS release will continue to receive backported fixes for at least half a
year. If you wish to use a fixed minor release in your project, we recommend
that you use an LTS release.
Each LTS release will continue to receive backported fixes for at least a year.
If you wish to use a fixed minor release in your project, we recommend that you
use an LTS release.
To use a fixed minor version, you can specify the version with a tilde. For
example, to specify that you wish to use the newest `1.8.x` patch release, you
example, to specify that you wish to use the newest `1.18.x` patch release, you
can use the following dependency specification:
```text
tokio = { version = "~1.8", features = [...] }
tokio = { version = "~1.18", features = [...] }
```
## License
+4 -4
View File
@@ -1,13 +1,13 @@
## Report a security issue
The Tokio project team welcomes security reports and is committed to providing prompt attention to security issues. Security issues should be reported privately via [[email protected]](mailto:[email protected]). Security issues should not be reported via the public Github Issue tracker.
The Tokio project team welcomes security reports and is committed to providing prompt attention to security issues. Security issues should be reported privately via [[email protected]](mailto:[email protected]). Security issues should not be reported via the public GitHub Issue tracker.
## Vulnerability coordination
Remediation of security vulnerabilities is prioritized by the project team. The project team coordinates remediation with third-party project stakeholders via [Github Security Advisories](https://help.github.com/en/github/managing-security-vulnerabilities/about-github-security-advisories). Third-party stakeholders may include the reporter of the issue, affected direct or indirect users of Tokio, and maintainers of upstream dependencies if applicable.
Remediation of security vulnerabilities is prioritized by the project team. The project team coordinates remediation with third-party project stakeholders via [GitHub Security Advisories](https://help.github.com/en/github/managing-security-vulnerabilities/about-github-security-advisories). Third-party stakeholders may include the reporter of the issue, affected direct or indirect users of Tokio, and maintainers of upstream dependencies if applicable.
Downstream project maintainers and Tokio users can request participation in coordination of applicable security issues by sending your contact email address, Github username(s) and any other salient information to [[email protected]](mailto:[email protected]). Participation in security issue coordination processes is at the discretion of the Tokio team.
Downstream project maintainers and Tokio users can request participation in coordination of applicable security issues by sending your contact email address, GitHub username(s) and any other salient information to [[email protected]](mailto:[email protected]). Participation in security issue coordination processes is at the discretion of the Tokio team.
## Security advisories
The project team is committed to transparency in the security issue disclosure process. The Tokio team announces security issues via [project Github Release notes](https://github.com/tokio-rs/tokio/releases) and the [RustSec advisory database](https://github.com/RustSec/advisory-db) (i.e. `cargo-audit`).
The project team is committed to transparency in the security issue disclosure process. The Tokio team announces security issues via [project GitHub Release notes](https://github.com/tokio-rs/tokio/releases) and the [RustSec advisory database](https://github.com/RustSec/advisory-db) (i.e. `cargo-audit`).
+36 -2
View File
@@ -2,14 +2,19 @@
name = "benches"
version = "0.0.0"
publish = false
edition = "2018"
edition = "2021"
[features]
test-util = ["tokio/test-util"]
[dependencies]
tokio = { version = "1.5.0", path = "../tokio", features = ["full"] }
bencher = "0.1.5"
rand = "0.8"
rand_chacha = "0.3"
[dev-dependencies]
tokio-util = { version = "0.6.6", path = "../tokio-util", features = ["full"] }
tokio-util = { version = "0.7.0", path = "../tokio-util", features = ["full"] }
tokio-stream = { path = "../tokio-stream" }
[target.'cfg(unix)'.dependencies]
@@ -25,11 +30,30 @@ name = "sync_mpsc"
path = "sync_mpsc.rs"
harness = false
[[bench]]
name = "sync_mpsc_oneshot"
path = "sync_mpsc_oneshot.rs"
harness = false
[[bench]]
name = "sync_watch"
path = "sync_watch.rs"
harness = false
[[bench]]
name = "rt_current_thread"
path = "rt_current_thread.rs"
harness = false
[[bench]]
name = "rt_multi_threaded"
path = "rt_multi_threaded.rs"
harness = false
[[bench]]
name = "sync_notify"
path = "sync_notify.rs"
harness = false
[[bench]]
name = "sync_rwlock"
@@ -50,3 +74,13 @@ harness = false
name = "fs"
path = "fs.rs"
harness = false
[[bench]]
name = "copy"
path = "copy.rs"
harness = false
[[bench]]
name = "time_now"
path = "time_now.rs"
harness = false
+238
View File
@@ -0,0 +1,238 @@
use bencher::{benchmark_group, benchmark_main, Bencher};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;
use tokio::io::{copy, repeat, AsyncRead, AsyncReadExt, AsyncWrite};
use tokio::time::{interval, Interval, MissedTickBehavior};
use std::task::Poll;
use std::time::Duration;
const KILO: usize = 1024;
// Tunable parameters if you want to change this benchmark. If reader and writer
// are matched in kilobytes per second, then this only exposes buffering to the
// benchmark.
const RNG_SEED: u64 = 0;
// How much data to copy in a single benchmark run
const SOURCE_SIZE: u64 = 256 * KILO as u64;
// Read side provides CHUNK_SIZE every READ_SERVICE_PERIOD. If it's not called
// frequently, it'll burst to catch up (representing OS buffers draining)
const CHUNK_SIZE: usize = 2 * KILO;
const READ_SERVICE_PERIOD: Duration = Duration::from_millis(1);
// Write side buffers up to WRITE_BUFFER, and flushes to disk every
// WRITE_SERVICE_PERIOD.
const WRITE_BUFFER: usize = 40 * KILO;
const WRITE_SERVICE_PERIOD: Duration = Duration::from_millis(20);
// How likely you are to have to wait for previously written data to be flushed
// because another writer claimed the buffer space
const PROBABILITY_FLUSH_WAIT: f64 = 0.1;
/// A slow writer that aims to simulate HDD behaviour under heavy load.
///
/// There is a limited buffer, which is fully drained on the next write after
/// a time limit is reached. Flush waits for the time limit to be reached
/// and then drains the buffer.
///
/// At random, the HDD will stall writers while it flushes out all buffers. If
/// this happens to you, you will be unable to write until the next time the
/// buffer is drained.
struct SlowHddWriter {
service_intervals: Interval,
blocking_rng: ChaCha20Rng,
buffer_size: usize,
buffer_used: usize,
}
impl SlowHddWriter {
fn new(service_interval: Duration, buffer_size: usize) -> Self {
let blocking_rng = ChaCha20Rng::seed_from_u64(RNG_SEED);
let mut service_intervals = interval(service_interval);
service_intervals.set_missed_tick_behavior(MissedTickBehavior::Delay);
Self {
service_intervals,
blocking_rng,
buffer_size,
buffer_used: 0,
}
}
fn service_write(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
// If we hit a service interval, the buffer can be cleared
let res = self.service_intervals.poll_tick(cx).map(|_| Ok(()));
if let Poll::Ready(_) = res {
self.buffer_used = 0;
}
res
}
fn write_bytes(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
writeable: usize,
) -> std::task::Poll<Result<usize, std::io::Error>> {
let service_res = self.as_mut().service_write(cx);
if service_res.is_pending() && self.blocking_rng.gen_bool(PROBABILITY_FLUSH_WAIT) {
return Poll::Pending;
}
let available = self.buffer_size - self.buffer_used;
if available == 0 {
assert!(service_res.is_pending());
Poll::Pending
} else {
let written = available.min(writeable);
self.buffer_used += written;
Poll::Ready(Ok(written))
}
}
}
impl Unpin for SlowHddWriter {}
impl AsyncWrite for SlowHddWriter {
fn poll_write(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &[u8],
) -> std::task::Poll<Result<usize, std::io::Error>> {
self.write_bytes(cx, buf.len())
}
fn poll_flush(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
self.service_write(cx)
}
fn poll_shutdown(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
self.service_write(cx)
}
fn poll_write_vectored(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
bufs: &[std::io::IoSlice<'_>],
) -> std::task::Poll<Result<usize, std::io::Error>> {
let writeable = bufs.into_iter().fold(0, |acc, buf| acc + buf.len());
self.write_bytes(cx, writeable)
}
fn is_write_vectored(&self) -> bool {
true
}
}
/// A reader that limits the maximum chunk it'll give you back
///
/// Simulates something reading from a slow link - you get one chunk per call,
/// and you are offered chunks on a schedule
struct ChunkReader {
data: Vec<u8>,
service_intervals: Interval,
}
impl ChunkReader {
fn new(chunk_size: usize, service_interval: Duration) -> Self {
let mut service_intervals = interval(service_interval);
service_intervals.set_missed_tick_behavior(MissedTickBehavior::Burst);
let data: Vec<u8> = std::iter::repeat(0).take(chunk_size).collect();
Self {
data,
service_intervals,
}
}
}
impl AsyncRead for ChunkReader {
fn poll_read(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
if self.service_intervals.poll_tick(cx).is_pending() {
return Poll::Pending;
}
buf.put_slice(&self.data[..buf.remaining().min(self.data.len())]);
Poll::Ready(Ok(()))
}
}
fn rt() -> tokio::runtime::Runtime {
tokio::runtime::Builder::new_current_thread()
.enable_time()
.build()
.unwrap()
}
fn copy_mem_to_mem(b: &mut Bencher) {
let rt = rt();
b.iter(|| {
let task = || async {
let mut source = repeat(0).take(SOURCE_SIZE);
let mut dest = Vec::new();
copy(&mut source, &mut dest).await.unwrap();
};
rt.block_on(task());
})
}
fn copy_mem_to_slow_hdd(b: &mut Bencher) {
let rt = rt();
b.iter(|| {
let task = || async {
let mut source = repeat(0).take(SOURCE_SIZE);
let mut dest = SlowHddWriter::new(WRITE_SERVICE_PERIOD, WRITE_BUFFER);
copy(&mut source, &mut dest).await.unwrap();
};
rt.block_on(task());
})
}
fn copy_chunk_to_mem(b: &mut Bencher) {
let rt = rt();
b.iter(|| {
let task = || async {
let mut source = ChunkReader::new(CHUNK_SIZE, READ_SERVICE_PERIOD).take(SOURCE_SIZE);
let mut dest = Vec::new();
copy(&mut source, &mut dest).await.unwrap();
};
rt.block_on(task());
})
}
fn copy_chunk_to_slow_hdd(b: &mut Bencher) {
let rt = rt();
b.iter(|| {
let task = || async {
let mut source = ChunkReader::new(CHUNK_SIZE, READ_SERVICE_PERIOD).take(SOURCE_SIZE);
let mut dest = SlowHddWriter::new(WRITE_SERVICE_PERIOD, WRITE_BUFFER);
copy(&mut source, &mut dest).await.unwrap();
};
rt.block_on(task());
})
}
benchmark_group!(
copy_bench,
copy_mem_to_mem,
copy_mem_to_slow_hdd,
copy_chunk_to_mem,
copy_chunk_to_slow_hdd,
);
benchmark_main!(copy_bench);
+1 -1
View File
@@ -21,7 +21,7 @@ fn rt() -> tokio::runtime::Runtime {
const BLOCK_COUNT: usize = 1_000;
const BUFFER_SIZE: usize = 4096;
const DEV_ZERO: &'static str = "/dev/zero";
const DEV_ZERO: &str = "/dev/zero";
fn async_read_codec(b: &mut Bencher) {
let rt = rt();
+83
View File
@@ -0,0 +1,83 @@
//! Benchmark implementation details of the threaded scheduler. These benches are
//! intended to be used as a form of regression testing and not as a general
//! purpose benchmark demonstrating real-world performance.
use tokio::runtime::{self, Runtime};
use bencher::{benchmark_group, benchmark_main, Bencher};
const NUM_SPAWN: usize = 1_000;
fn spawn_many_local(b: &mut Bencher) {
let rt = rt();
let mut handles = Vec::with_capacity(NUM_SPAWN);
b.iter(|| {
rt.block_on(async {
for _ in 0..NUM_SPAWN {
handles.push(tokio::spawn(async move {}));
}
for handle in handles.drain(..) {
handle.await.unwrap();
}
});
});
}
fn spawn_many_remote_idle(b: &mut Bencher) {
let rt = rt();
let rt_handle = rt.handle();
let mut handles = Vec::with_capacity(NUM_SPAWN);
b.iter(|| {
for _ in 0..NUM_SPAWN {
handles.push(rt_handle.spawn(async {}));
}
rt.block_on(async {
for handle in handles.drain(..) {
handle.await.unwrap();
}
});
});
}
fn spawn_many_remote_busy(b: &mut Bencher) {
let rt = rt();
let rt_handle = rt.handle();
let mut handles = Vec::with_capacity(NUM_SPAWN);
rt.spawn(async {
fn iter() {
tokio::spawn(async { iter() });
}
iter()
});
b.iter(|| {
for _ in 0..NUM_SPAWN {
handles.push(rt_handle.spawn(async {}));
}
rt.block_on(async {
for handle in handles.drain(..) {
handle.await.unwrap();
}
});
});
}
fn rt() -> Runtime {
runtime::Builder::new_current_thread().build().unwrap()
}
benchmark_group!(
scheduler,
spawn_many_local,
spawn_many_remote_idle,
spawn_many_remote_busy
);
benchmark_main!(scheduler);
+117 -5
View File
@@ -6,13 +6,16 @@ use tokio::runtime::{self, Runtime};
use tokio::sync::oneshot;
use bencher::{benchmark_group, benchmark_main, Bencher};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::{mpsc, Arc};
use std::time::{Duration, Instant};
fn spawn_many(b: &mut Bencher) {
const NUM_SPAWN: usize = 10_000;
const NUM_WORKERS: usize = 4;
const NUM_SPAWN: usize = 10_000;
const STALL_DUR: Duration = Duration::from_micros(10);
fn spawn_many_local(b: &mut Bencher) {
let rt = rt();
let (tx, rx) = mpsc::sync_channel(1000);
@@ -38,6 +41,99 @@ fn spawn_many(b: &mut Bencher) {
});
}
fn spawn_many_remote_idle(b: &mut Bencher) {
let rt = rt();
let mut handles = Vec::with_capacity(NUM_SPAWN);
b.iter(|| {
for _ in 0..NUM_SPAWN {
handles.push(rt.spawn(async {}));
}
rt.block_on(async {
for handle in handles.drain(..) {
handle.await.unwrap();
}
});
});
}
// The runtime is busy with tasks that consume CPU time and yield. Yielding is a
// lower notification priority than spawning / regular notification.
fn spawn_many_remote_busy1(b: &mut Bencher) {
let rt = rt();
let rt_handle = rt.handle();
let mut handles = Vec::with_capacity(NUM_SPAWN);
let flag = Arc::new(AtomicBool::new(true));
// Spawn some tasks to keep the runtimes busy
for _ in 0..(2 * NUM_WORKERS) {
let flag = flag.clone();
rt.spawn(async move {
while flag.load(Relaxed) {
tokio::task::yield_now().await;
stall();
}
});
}
b.iter(|| {
for _ in 0..NUM_SPAWN {
handles.push(rt_handle.spawn(async {}));
}
rt.block_on(async {
for handle in handles.drain(..) {
handle.await.unwrap();
}
});
});
flag.store(false, Relaxed);
}
// The runtime is busy with tasks that consume CPU time and spawn new high-CPU
// tasks. Spawning goes via a higher notification priority than yielding.
fn spawn_many_remote_busy2(b: &mut Bencher) {
const NUM_SPAWN: usize = 1_000;
let rt = rt();
let rt_handle = rt.handle();
let mut handles = Vec::with_capacity(NUM_SPAWN);
let flag = Arc::new(AtomicBool::new(true));
// Spawn some tasks to keep the runtimes busy
for _ in 0..(NUM_WORKERS) {
let flag = flag.clone();
fn iter(flag: Arc<AtomicBool>) {
tokio::spawn(async {
if flag.load(Relaxed) {
stall();
iter(flag);
}
});
}
rt.spawn(async {
iter(flag);
});
}
b.iter(|| {
for _ in 0..NUM_SPAWN {
handles.push(rt_handle.spawn(async {}));
}
rt.block_on(async {
for handle in handles.drain(..) {
handle.await.unwrap();
}
});
});
flag.store(false, Relaxed);
}
fn yield_many(b: &mut Bencher) {
const NUM_YIELD: usize = 1_000;
const TASKS: usize = 200;
@@ -140,12 +236,28 @@ fn chained_spawn(b: &mut Bencher) {
fn rt() -> Runtime {
runtime::Builder::new_multi_thread()
.worker_threads(4)
.worker_threads(NUM_WORKERS)
.enable_all()
.build()
.unwrap()
}
benchmark_group!(scheduler, spawn_many, ping_pong, yield_many, chained_spawn,);
fn stall() {
let now = Instant::now();
while now.elapsed() < STALL_DUR {
std::thread::yield_now();
}
}
benchmark_group!(
scheduler,
spawn_many_local,
spawn_many_remote_idle,
spawn_many_remote_busy1,
spawn_many_remote_busy2,
ping_pong,
yield_many,
chained_spawn,
);
benchmark_main!(scheduler);
+53
View File
@@ -0,0 +1,53 @@
use bencher::{benchmark_group, benchmark_main, Bencher};
use tokio::{
runtime::Runtime,
sync::{mpsc, oneshot},
};
fn request_reply_current_thread(b: &mut Bencher) {
let rt = tokio::runtime::Builder::new_current_thread()
.build()
.unwrap();
request_reply(b, rt);
}
fn request_reply_multi_threaded(b: &mut Bencher) {
let rt = tokio::runtime::Builder::new_multi_thread()
.worker_threads(1)
.build()
.unwrap();
request_reply(b, rt);
}
fn request_reply(b: &mut Bencher, rt: Runtime) {
let tx = rt.block_on(async move {
let (tx, mut rx) = mpsc::channel::<oneshot::Sender<()>>(10);
tokio::spawn(async move {
while let Some(reply) = rx.recv().await {
reply.send(()).unwrap();
}
});
tx
});
b.iter(|| {
let task_tx = tx.clone();
rt.block_on(async move {
for _ in 0..1_000 {
let (o_tx, o_rx) = oneshot::channel();
task_tx.send(o_tx).await.unwrap();
let _ = o_rx.await;
}
})
});
}
benchmark_group!(
sync_mpsc_oneshot_group,
request_reply_current_thread,
request_reply_multi_threaded,
);
benchmark_main!(sync_mpsc_oneshot_group);
+90
View File
@@ -0,0 +1,90 @@
use bencher::Bencher;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use tokio::sync::Notify;
fn rt() -> tokio::runtime::Runtime {
tokio::runtime::Builder::new_multi_thread()
.worker_threads(6)
.build()
.unwrap()
}
fn notify_waiters<const N_WAITERS: usize>(b: &mut Bencher) {
let rt = rt();
let notify = Arc::new(Notify::new());
let counter = Arc::new(AtomicUsize::new(0));
for _ in 0..N_WAITERS {
rt.spawn({
let notify = notify.clone();
let counter = counter.clone();
async move {
loop {
notify.notified().await;
counter.fetch_add(1, Ordering::Relaxed);
}
}
});
}
const N_ITERS: usize = 500;
b.iter(|| {
counter.store(0, Ordering::Relaxed);
loop {
notify.notify_waiters();
if counter.load(Ordering::Relaxed) >= N_ITERS {
break;
}
}
});
}
fn notify_one<const N_WAITERS: usize>(b: &mut Bencher) {
let rt = rt();
let notify = Arc::new(Notify::new());
let counter = Arc::new(AtomicUsize::new(0));
for _ in 0..N_WAITERS {
rt.spawn({
let notify = notify.clone();
let counter = counter.clone();
async move {
loop {
notify.notified().await;
counter.fetch_add(1, Ordering::Relaxed);
}
}
});
}
const N_ITERS: usize = 500;
b.iter(|| {
counter.store(0, Ordering::Relaxed);
loop {
notify.notify_one();
if counter.load(Ordering::Relaxed) >= N_ITERS {
break;
}
}
});
}
bencher::benchmark_group!(
notify_waiters_simple,
notify_waiters::<10>,
notify_waiters::<50>,
notify_waiters::<100>,
notify_waiters::<200>,
notify_waiters::<500>
);
bencher::benchmark_group!(
notify_one_simple,
notify_one::<10>,
notify_one::<50>,
notify_one::<100>,
notify_one::<200>,
notify_one::<500>
);
bencher::benchmark_main!(notify_waiters_simple, notify_one_simple);
+5 -5
View File
@@ -14,7 +14,7 @@ fn read_uncontended(b: &mut Bencher) {
rt.block_on(async move {
for _ in 0..6 {
let read = lock.read().await;
black_box(read);
let _read = black_box(read);
}
})
});
@@ -28,7 +28,7 @@ fn read_concurrent_uncontended_multi(b: &mut Bencher) {
async fn task(lock: Arc<RwLock<()>>) {
let read = lock.read().await;
black_box(read);
let _read = black_box(read);
}
let lock = Arc::new(RwLock::new(()));
@@ -55,7 +55,7 @@ fn read_concurrent_uncontended(b: &mut Bencher) {
async fn task(lock: Arc<RwLock<()>>) {
let read = lock.read().await;
black_box(read);
let _read = black_box(read);
}
let lock = Arc::new(RwLock::new(()));
@@ -82,7 +82,7 @@ fn read_concurrent_contended_multi(b: &mut Bencher) {
async fn task(lock: Arc<RwLock<()>>) {
let read = lock.read().await;
black_box(read);
let _read = black_box(read);
}
let lock = Arc::new(RwLock::new(()));
@@ -110,7 +110,7 @@ fn read_concurrent_contended(b: &mut Bencher) {
async fn task(lock: Arc<RwLock<()>>) {
let read = lock.read().await;
black_box(read);
let _read = black_box(read);
}
let lock = Arc::new(RwLock::new(()));
+64
View File
@@ -0,0 +1,64 @@
use bencher::{black_box, Bencher};
use rand::prelude::*;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use tokio::sync::{watch, Notify};
fn rt() -> tokio::runtime::Runtime {
tokio::runtime::Builder::new_multi_thread()
.worker_threads(6)
.build()
.unwrap()
}
fn do_work(rng: &mut impl RngCore) -> u32 {
use std::fmt::Write;
let mut message = String::new();
for i in 1..=10 {
let _ = write!(&mut message, " {i}={}", rng.gen::<f64>());
}
message
.as_bytes()
.iter()
.map(|&c| c as u32)
.fold(0, u32::wrapping_add)
}
fn contention_resubscribe(b: &mut Bencher) {
const NTASK: u64 = 1000;
let rt = rt();
let (snd, rcv) = watch::channel(0i32);
let wg = Arc::new((AtomicU64::new(0), Notify::new()));
for n in 0..NTASK {
let mut rcv = rcv.clone();
let wg = wg.clone();
let mut rng = rand::rngs::StdRng::seed_from_u64(n);
rt.spawn(async move {
while rcv.changed().await.is_ok() {
let _ = *rcv.borrow(); // contend on rwlock
let r = do_work(&mut rng);
let _ = black_box(r);
if wg.0.fetch_sub(1, Ordering::Release) == 1 {
wg.1.notify_one();
}
}
});
}
b.iter(|| {
rt.block_on(async {
for _ in 0..100 {
assert_eq!(wg.0.fetch_add(NTASK, Ordering::Relaxed), 0);
let _ = snd.send(black_box(42));
while wg.0.load(Ordering::Acquire) > 0 {
wg.1.notified().await;
}
}
});
});
}
bencher::benchmark_group!(contention, contention_resubscribe);
bencher::benchmark_main!(contention);
+25
View File
@@ -0,0 +1,25 @@
//! Benchmark spawning a task onto the basic and threaded Tokio executors.
//! This essentially measure the time to enqueue a task in the local and remote
//! case.
#[macro_use]
extern crate bencher;
use bencher::{black_box, Bencher};
fn time_now_current_thread(bench: &mut Bencher) {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_time()
.build()
.unwrap();
bench.iter(|| {
rt.block_on(async {
black_box(tokio::time::Instant::now());
})
})
}
bencher::benchmark_group!(time_now, time_now_current_thread,);
bencher::benchmark_main!(time_now);
+11 -8
View File
@@ -2,17 +2,17 @@
name = "examples"
version = "0.0.0"
publish = false
edition = "2018"
edition = "2021"
# If you copy one of the examples into a new project, you should be using
# [dependencies] instead.
# [dependencies] instead, and delete the **path**.
[dev-dependencies]
tokio = { version = "1.0.0", path = "../tokio",features = ["full", "tracing"] }
tokio-util = { version = "0.6.3", path = "../tokio-util",features = ["full"] }
tokio = { version = "1.0.0", path = "../tokio", features = ["full", "tracing"] }
tokio-util = { version = "0.7.0", path = "../tokio-util", features = ["full"] }
tokio-stream = { version = "0.1", path = "../tokio-stream" }
tracing = "0.1"
tracing-subscriber = { version = "0.2.7", default-features = false, features = ["fmt", "ansi", "env-filter", "chrono", "tracing-log"] }
tracing-subscriber = { version = "0.3.1", default-features = false, features = ["fmt", "ansi", "env-filter", "tracing-log"] }
bytes = "1.0.0"
futures = { version = "0.3.0", features = ["thread-pool"]}
http = "0.2"
@@ -24,8 +24,8 @@ httpdate = "1.0"
once_cell = "1.5.2"
rand = "0.8.3"
[target.'cfg(windows)'.dev-dependencies.winapi]
version = "0.3.8"
[target.'cfg(windows)'.dev-dependencies.windows-sys]
version = "0.48"
[[example]]
name = "chat"
@@ -75,7 +75,6 @@ path = "tinyhttp.rs"
name = "custom-executor"
path = "custom-executor.rs"
[[example]]
name = "custom-executor-tokio-context"
path = "custom-executor-tokio-context.rs"
@@ -91,3 +90,7 @@ path = "named-pipe-ready.rs"
[[example]]
name = "named-pipe-multi-client"
path = "named-pipe-multi-client.rs"
[[example]]
name = "dump"
path = "dump.rs"
+90
View File
@@ -0,0 +1,90 @@
//! This example demonstrates tokio's experimental task dumping functionality.
//! This application deadlocks. Input CTRL+C to display traces of each task, or
//! input CTRL+C twice within 1 second to quit.
#[cfg(all(
tokio_unstable,
tokio_taskdump,
target_os = "linux",
any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")
))]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use std::sync::Arc;
use tokio::sync::Barrier;
#[inline(never)]
async fn a(barrier: Arc<Barrier>) {
b(barrier).await
}
#[inline(never)]
async fn b(barrier: Arc<Barrier>) {
c(barrier).await
}
#[inline(never)]
async fn c(barrier: Arc<Barrier>) {
barrier.wait().await;
}
// Prints a task dump upon receipt of CTRL+C, or returns if CTRL+C is
// inputted twice within a second.
async fn dump_or_quit() {
use tokio::time::{timeout, Duration, Instant};
let handle = tokio::runtime::Handle::current();
let mut last_signal: Option<Instant> = None;
// wait for CTRL+C
while let Ok(_) = tokio::signal::ctrl_c().await {
// exit if a CTRL+C is inputted twice within 1 second
if let Some(time_since_last_signal) = last_signal.map(|i| i.elapsed()) {
if time_since_last_signal < Duration::from_secs(1) {
return;
}
}
last_signal = Some(Instant::now());
// capture a dump, and print each trace
println!("{:-<80}", "");
if let Ok(dump) = timeout(Duration::from_secs(2), handle.dump()).await {
for (i, task) in dump.tasks().iter().enumerate() {
let trace = task.trace();
println!("TASK {i}:");
println!("{trace}\n");
}
} else {
println!("Task dumping timed out. Use a native debugger (like gdb) to debug the deadlock.");
}
println!("{:-<80}", "");
println!("Input CTRL+C twice within 1 second to exit.");
}
}
println!("This program has a deadlock.");
println!("Input CTRL+C to print a task dump.");
println!("Input CTRL+C twice within 1 second to exit.");
// oops! this barrier waits for one more task than will ever come.
let barrier = Arc::new(Barrier::new(3));
let task_1 = tokio::spawn(a(barrier.clone()));
let task_2 = tokio::spawn(a(barrier));
tokio::select!(
_ = dump_or_quit() => {},
_ = task_1 => {},
_ = task_2 => {},
);
Ok(())
}
#[cfg(not(all(
tokio_unstable,
tokio_taskdump,
target_os = "linux",
any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")
)))]
fn main() {
println!("task dumps are not available")
}
+2 -4
View File
@@ -1,9 +1,7 @@
//! Hello world server.
//!
//! A simple client that opens a TCP stream, writes "hello world\n", and closes
//! the connection.
//!
//! You can test this out by running:
//! To start a server that this client can talk to on port 6142, you can use this command:
//!
//! ncat -l 6142
//!
@@ -26,7 +24,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
let mut stream = TcpStream::connect("127.0.0.1:6142").await?;
println!("created stream");
let result = stream.write(b"hello world\n").await;
let result = stream.write_all(b"hello world\n").await;
println!("wrote to stream; success={:?}", result.is_ok());
Ok(())
+2 -2
View File
@@ -6,7 +6,7 @@ async fn windows_main() -> io::Result<()> {
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
use tokio::time;
use winapi::shared::winerror;
use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
const PIPE_NAME: &str = r"\\.\pipe\named-pipe-multi-client";
const N: usize = 10;
@@ -59,7 +59,7 @@ async fn windows_main() -> io::Result<()> {
let mut client = loop {
match ClientOptions::new().open(PIPE_NAME) {
Ok(client) => break client,
Err(e) if e.raw_os_error() == Some(winerror::ERROR_PIPE_BUSY as i32) => (),
Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY as i32) => (),
Err(e) => return Err(e),
}
+1 -1
View File
@@ -149,7 +149,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
}
fn handle_request(line: &str, db: &Arc<Database>) -> Response {
let request = match Request::parse(&line) {
let request = match Request::parse(line) {
Ok(req) => req,
Err(e) => return Response::Error { msg: e },
};
+5 -2
View File
@@ -180,8 +180,11 @@ impl Decoder for Http {
headers[i] = Some((k, v));
}
let method = http::Method::try_from(r.method.unwrap())
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
(
toslice(r.method.unwrap().as_bytes()),
method,
toslice(r.path.unwrap().as_bytes()),
r.version.unwrap(),
amt,
@@ -195,7 +198,7 @@ impl Decoder for Http {
}
let data = src.split_to(amt).freeze();
let mut ret = Request::builder();
ret = ret.method(&data[method.0..method.1]);
ret = ret.method(method);
let s = data.slice(path.0..path.1);
let s = unsafe { String::from_utf8_unchecked(Vec::from(s.as_ref())) };
ret = ret.uri(s);
+16
View File
@@ -0,0 +1,16 @@
[build]
command = """
rustup install nightly --profile minimal && cargo doc --no-deps --all-features
"""
publish = "target/doc"
[build.environment]
RUSTDOCFLAGS="""
--cfg docsrs \
--cfg tokio_unstable \
"""
RUSTFLAGS="--cfg tokio_unstable --cfg docsrs"
[[redirects]]
from = "/"
to = "/tokio"
+1 -1
View File
@@ -2,7 +2,7 @@
name = "stress-test"
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
edition = "2018"
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+40
View File
@@ -0,0 +1,40 @@
{
"arch": "x86",
"cpu": "pentium4",
"crt-static-respected": true,
"data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128",
"dynamic-linking": true,
"env": "gnu",
"has-rpath": true,
"has-thread-local": true,
"llvm-target": "i686-unknown-linux-gnu",
"max-atomic-width": 32,
"os": "linux",
"position-independent-executables": true,
"pre-link-args": {
"gcc": [
"-m32"
]
},
"relro-level": "full",
"stack-probes": {
"kind": "inline-or-call",
"min-llvm-version-for-inline": [
16,
0,
0
]
},
"supported-sanitizers": [
"address"
],
"supported-split-debuginfo": [
"packed",
"unpacked",
"off"
],
"target-family": [
"unix"
],
"target-pointer-width": "32"
}
+1 -1
View File
@@ -2,7 +2,7 @@
name = "tests-build"
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
edition = "2018"
edition = "2021"
publish = false
[features]
+8
View File
@@ -1,2 +1,10 @@
Tests the various combination of feature flags. This is broken out to a separate
crate to work around limitations with cargo features.
To run all of the tests in this directory, run the following commands:
```
cargo test --features full
cargo test --features rt
```
If one of the tests fail, you can pass `TRYBUILD=overwrite` to the `cargo test`
command that failed to have it regenerate the test output.
@@ -1,4 +1,4 @@
error: function is never used: `f`
error: function `f` is never used
--> $DIR/macros_dead_code.rs:6:10
|
6 | async fn f() {}
@@ -1,3 +1,5 @@
#![deny(duplicate_macro_attributes)]
use tests_build::tokio;
#[tokio::main]
@@ -33,6 +35,12 @@ async fn test_worker_threads_not_int() {}
#[tokio::test(flavor = "current_thread", worker_threads = 4)]
async fn test_worker_threads_and_current_thread() {}
#[tokio::test(crate = 456)]
async fn test_crate_not_path_int() {}
#[tokio::test(crate = "456")]
async fn test_crate_not_path_invalid() {}
#[tokio::test]
#[test]
async fn test_has_second_test_attr() {}
@@ -1,71 +1,95 @@
error: the `async` keyword is missing from the function declaration
--> $DIR/macros_invalid_input.rs:4:1
--> $DIR/macros_invalid_input.rs:6:1
|
4 | fn main_is_not_async() {}
6 | fn main_is_not_async() {}
| ^^
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`
--> $DIR/macros_invalid_input.rs:6:15
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`
--> $DIR/macros_invalid_input.rs:8:15
|
6 | #[tokio::main(foo)]
8 | #[tokio::main(foo)]
| ^^^
error: Must have specified ident
--> $DIR/macros_invalid_input.rs:9:15
|
9 | #[tokio::main(threadpool::bar)]
| ^^^^^^^^^^^^^^^
--> $DIR/macros_invalid_input.rs:11:15
|
11 | #[tokio::main(threadpool::bar)]
| ^^^^^^^^^^^^^^^
error: the `async` keyword is missing from the function declaration
--> $DIR/macros_invalid_input.rs:13:1
--> $DIR/macros_invalid_input.rs:15:1
|
13 | fn test_is_not_async() {}
15 | fn test_is_not_async() {}
| ^^
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`
--> $DIR/macros_invalid_input.rs:15:15
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`
--> $DIR/macros_invalid_input.rs:17:15
|
15 | #[tokio::test(foo)]
17 | #[tokio::test(foo)]
| ^^^
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`
--> $DIR/macros_invalid_input.rs:18:15
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`
--> $DIR/macros_invalid_input.rs:20:15
|
18 | #[tokio::test(foo = 123)]
20 | #[tokio::test(foo = 123)]
| ^^^^^^^^^
error: Failed to parse value of `flavor` as string.
--> $DIR/macros_invalid_input.rs:21:24
--> $DIR/macros_invalid_input.rs:23:24
|
21 | #[tokio::test(flavor = 123)]
23 | #[tokio::test(flavor = 123)]
| ^^^
error: No such runtime flavor `foo`. The runtime flavors are `current_thread` and `multi_thread`.
--> $DIR/macros_invalid_input.rs:24:24
--> $DIR/macros_invalid_input.rs:26:24
|
24 | #[tokio::test(flavor = "foo")]
26 | #[tokio::test(flavor = "foo")]
| ^^^^^
error: The `start_paused` option requires the `current_thread` runtime flavor. Use `#[tokio::test(flavor = "current_thread")]`
--> $DIR/macros_invalid_input.rs:27:55
--> $DIR/macros_invalid_input.rs:29:55
|
27 | #[tokio::test(flavor = "multi_thread", start_paused = false)]
29 | #[tokio::test(flavor = "multi_thread", start_paused = false)]
| ^^^^^
error: Failed to parse value of `worker_threads` as integer.
--> $DIR/macros_invalid_input.rs:30:57
--> $DIR/macros_invalid_input.rs:32:57
|
30 | #[tokio::test(flavor = "multi_thread", worker_threads = "foo")]
32 | #[tokio::test(flavor = "multi_thread", worker_threads = "foo")]
| ^^^^^
error: The `worker_threads` option requires the `multi_thread` runtime flavor. Use `#[tokio::test(flavor = "multi_thread")]`
--> $DIR/macros_invalid_input.rs:33:59
--> $DIR/macros_invalid_input.rs:35:59
|
33 | #[tokio::test(flavor = "current_thread", worker_threads = 4)]
35 | #[tokio::test(flavor = "current_thread", worker_threads = 4)]
| ^
error: second test attribute is supplied
--> $DIR/macros_invalid_input.rs:37:1
error: Failed to parse value of `crate` as path.
--> $DIR/macros_invalid_input.rs:38:23
|
37 | #[test]
38 | #[tokio::test(crate = 456)]
| ^^^
error: Failed to parse value of `crate` as path: "456"
--> $DIR/macros_invalid_input.rs:41:23
|
41 | #[tokio::test(crate = "456")]
| ^^^^^
error: second test attribute is supplied
--> $DIR/macros_invalid_input.rs:45:1
|
45 | #[test]
| ^^^^^^^
error: duplicated attribute
--> $DIR/macros_invalid_input.rs:45:1
|
45 | #[test]
| ^^^^^^^
|
note: the lint level is defined here
--> $DIR/macros_invalid_input.rs:1:9
|
1 | #![deny(duplicate_macro_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,4 +23,13 @@ async fn extra_semicolon() -> Result<(), ()> {
Ok(());
}
// https://github.com/tokio-rs/tokio/issues/4635
#[allow(redundant_semicolons)]
#[rustfmt::skip]
#[tokio::main]
async fn issue_4635() {
return 1;
;
}
fn main() {}
@@ -1,45 +1,47 @@
error[E0308]: mismatched types
--> $DIR/macros_type_mismatch.rs:5:5
--> tests/fail/macros_type_mismatch.rs:5:5
|
4 | async fn missing_semicolon_or_return_type() {
| - help: a return type might be missing here: `-> _`
5 | Ok(())
| ^^^^^^ expected `()`, found enum `Result`
| ^^^^^^ expected `()`, found `Result<(), _>`
|
= note: expected unit type `()`
found enum `Result<(), _>`
help: consider using a semicolon here
|
5 | Ok(());
| +
help: try adding a return type
|
4 | async fn missing_semicolon_or_return_type() -> Result<(), _> {
| ++++++++++++++++
error[E0308]: mismatched types
--> $DIR/macros_type_mismatch.rs:10:5
--> tests/fail/macros_type_mismatch.rs:10:5
|
9 | async fn missing_return_type() {
| - help: try adding a return type: `-> Result<(), _>`
| - help: a return type might be missing here: `-> _`
10 | return Ok(());
| ^^^^^^^^^^^^^^ expected `()`, found enum `Result`
| ^^^^^^^^^^^^^^ expected `()`, found `Result<(), _>`
|
= note: expected unit type `()`
found enum `Result<(), _>`
error[E0308]: mismatched types
--> $DIR/macros_type_mismatch.rs:23:5
--> tests/fail/macros_type_mismatch.rs:23:5
|
14 | async fn extra_semicolon() -> Result<(), ()> {
| -------------- expected `Result<(), ()>` because of return type
...
23 | Ok(());
| ^^^^^^^ expected enum `Result`, found `()`
| ^^^^^^^ expected `Result<(), ()>`, found `()`
|
= note: expected enum `Result<(), ()>`
found unit type `()`
help: try using a variant of the expected enum
help: try adding an expression at the end of the block
|
23 | Ok(Ok(());)
23 ~ Ok(());;
24 + Ok(())
|
23 | Err(Ok(());)
error[E0308]: mismatched types
--> tests/fail/macros_type_mismatch.rs:32:5
|
30 | async fn issue_4635() {
| - help: try adding a return type: `-> i32`
31 | return 1;
32 | ;
| ^ expected `()`, found integer
+21 -2
View File
@@ -2,7 +2,7 @@
name = "tests-integration"
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
edition = "2018"
edition = "2021"
publish = false
[[bin]]
@@ -16,11 +16,29 @@ required-features = ["rt-net"]
name = "test-process-signal"
required-features = ["rt-process-signal"]
[[test]]
name = "macros_main"
[[test]]
name = "macros_pin"
[[test]]
name = "macros_select"
[[test]]
name = "rt_yield"
required-features = ["rt", "macros", "sync"]
[features]
# For mem check
rt-net = ["tokio/rt", "tokio/rt-multi-thread", "tokio/net"]
# For test-process-signal
rt-process-signal = ["rt", "tokio/process", "tokio/signal"]
rt-process-signal = ["rt-net", "tokio/process", "tokio/signal"]
# For testing wasi + rt/macros/sync features
#
# This is an explicit feature so we can use `cargo hack` testing single features
# instead of all possible permutations.
wasi-rt = ["rt", "macros", "sync"]
full = [
"macros",
@@ -40,3 +58,4 @@ tokio = { path = "../tokio" }
tokio-test = { path = "../tokio-test", optional = true }
doc-comment = "0.3.1"
futures = { version = "0.3.0", features = ["async-await"] }
bytes = "1.0.0"
+5 -1
View File
@@ -1,4 +1,8 @@
#![cfg(all(feature = "macros", feature = "rt"))]
#![cfg(all(
feature = "macros",
feature = "rt-multi-thread",
not(target_os = "wasi")
))]
#[tokio::main]
async fn basic_main() -> usize {
+1
View File
@@ -4,6 +4,7 @@ use futures::channel::oneshot;
use futures::executor::block_on;
use std::thread;
#[cfg_attr(target_os = "wasi", ignore = "WASI: std::thread::spawn not supported")]
#[test]
fn join_with_select() {
block_on(async {
+52 -2
View File
@@ -1,5 +1,5 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "full")]
#![cfg(all(feature = "full", not(target_os = "wasi")))]
use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};
use tokio::join;
@@ -7,7 +7,6 @@ use tokio::process::{Child, Command};
use tokio_test::assert_ok;
use futures::future::{self, FutureExt};
use std::convert::TryInto;
use std::env;
use std::io;
use std::process::{ExitStatus, Stdio};
@@ -190,3 +189,54 @@ async fn pipe_from_one_command_to_another() {
assert!(second_status.expect("second status").success());
assert!(third_status.expect("third status").success());
}
#[tokio::test]
async fn vectored_writes() {
use bytes::{Buf, Bytes};
use std::{io::IoSlice, pin::Pin};
use tokio::io::AsyncWrite;
let mut cat = cat().spawn().unwrap();
let mut stdin = cat.stdin.take().unwrap();
let are_writes_vectored = stdin.is_write_vectored();
let mut stdout = cat.stdout.take().unwrap();
let write = async {
let mut input = Bytes::from_static(b"hello\n").chain(Bytes::from_static(b"world!\n"));
let mut writes_completed = 0;
futures::future::poll_fn(|cx| loop {
let mut slices = [IoSlice::new(&[]); 2];
let vectored = input.chunks_vectored(&mut slices);
if vectored == 0 {
return std::task::Poll::Ready(std::io::Result::Ok(()));
}
let n = futures::ready!(Pin::new(&mut stdin).poll_write_vectored(cx, &slices))?;
writes_completed += 1;
input.advance(n);
})
.await?;
drop(stdin);
std::io::Result::Ok(writes_completed)
};
let read = async {
let mut buffer = Vec::with_capacity(6 + 7);
stdout.read_to_end(&mut buffer).await?;
std::io::Result::Ok(buffer)
};
let (write, read, status) = future::join3(write, read, cat.wait()).await;
assert!(status.unwrap().success());
let writes_completed = write.unwrap();
// on unix our small payload should always fit in whatever default sized pipe with a single
// syscall. if multiple are used, then the forwarding does not work, or we are on a platform
// for which the `std` does not support vectored writes.
assert_eq!(writes_completed == 1, are_writes_vectored);
assert_eq!(&read.unwrap(), b"hello\nworld!\n");
}
+41
View File
@@ -0,0 +1,41 @@
use tokio::sync::oneshot;
use tokio::task;
async fn spawn_send() {
let (tx, rx) = oneshot::channel();
let task = tokio::spawn(async {
for _ in 0..10 {
task::yield_now().await;
}
tx.send("done").unwrap();
});
assert_eq!("done", rx.await.unwrap());
task.await.unwrap();
}
#[tokio::main(flavor = "current_thread")]
async fn entry_point() {
spawn_send().await;
}
#[tokio::test]
async fn test_macro() {
spawn_send().await;
}
#[test]
fn main_macro() {
entry_point();
}
#[test]
fn manual_rt() {
let rt = tokio::runtime::Builder::new_current_thread()
.build()
.unwrap();
rt.block_on(async { spawn_send().await });
}
+61
View File
@@ -1,3 +1,64 @@
# 2.1.0 (April 25th, 2023)
- macros: fix typo in `#[tokio::test]` docs ([#5636])
- macros: make entrypoints more efficient ([#5621])
[#5621]: https://github.com/tokio-rs/tokio/pull/5621
[#5636]: https://github.com/tokio-rs/tokio/pull/5636
# 2.0.0 (March 24th, 2023)
This major release updates the dependency on the syn crate to 2.0.0, and
increases the MSRV to 1.56.
As part of this release, we are adopting a policy of depending on a specific minor
release of tokio-macros. This prevents Tokio from being able to pull in many different
versions of tokio-macros.
- macros: update `syn` ([#5572])
- macros: accept path as crate rename ([#5557])
[#5572]: https://github.com/tokio-rs/tokio/pull/5572
[#5557]: https://github.com/tokio-rs/tokio/pull/5557
# 1.8.2 (November 30th, 2022)
- fix a regression introduced in 1.8.1 ([#5244])
[#5244]: https://github.com/tokio-rs/tokio/pull/5244
# 1.8.1 (November 29th, 2022)
(yanked)
- macros: Pin Futures in `#[tokio::test]` to stack ([#5205])
- macros: Reduce usage of last statement spans in proc-macros ([#5092])
- macros: Improve the documentation for `#[tokio::test]` ([#4761])
[#5205]: https://github.com/tokio-rs/tokio/pull/5205
[#5092]: https://github.com/tokio-rs/tokio/pull/5092
[#4761]: https://github.com/tokio-rs/tokio/pull/4761
# 1.8.0 (June 4th, 2022)
- macros: always emit return statement ([#4636])
- macros: support setting a custom crate name for `#[tokio::main]` and `#[tokio::test]` ([#4613])
[#4613]: https://github.com/tokio-rs/tokio/pull/4613
[#4636]: https://github.com/tokio-rs/tokio/pull/4636
# 1.7.0 (December 15th, 2021)
- macros: address remaining `clippy::semicolon_if_nothing_returned` warning ([#4252])
[#4252]: https://github.com/tokio-rs/tokio/pull/4252
# 1.6.0 (November 16th, 2021)
- macros: fix mut patterns in `select!` macro ([#4211])
[#4211]: https://github.com/tokio-rs/tokio/pull/4211
# 1.5.1 (October 29th, 2021)
- macros: fix type resolution error in `#[tokio::main]` ([#4176])
+5 -7
View File
@@ -2,17 +2,15 @@
name = "tokio-macros"
# When releasing to crates.io:
# - Remove path dependencies
# - Update doc url
# - Cargo.toml
# - Update CHANGELOG.md.
# - Create "tokio-macros-1.0.x" git tag.
version = "1.5.1"
edition = "2018"
# - Create "tokio-macros-1.x.y" git tag.
version = "2.1.0"
edition = "2021"
rust-version = "1.56"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://tokio.rs"
documentation = "https://docs.rs/tokio-macros/1.5.1/tokio_macros"
description = """
Tokio's proc macros.
"""
@@ -26,7 +24,7 @@ proc-macro = true
[dependencies]
proc-macro2 = "1.0.7"
quote = "1"
syn = { version = "1.0.56", features = ["full"] }
syn = { version = "2.0", features = ["full"] }
[dev-dependencies]
tokio = { version = "1.0.0", path = "../tokio", features = ["full"] }
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2021 Tokio Contributors
Copyright (c) 2023 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
+234 -71
View File
@@ -1,10 +1,10 @@
use proc_macro::TokenStream;
use proc_macro2::Span;
use proc_macro2::{Span, TokenStream, TokenTree};
use quote::{quote, quote_spanned, ToTokens};
use syn::parse::Parser;
use syn::parse::{Parse, ParseStream, Parser};
use syn::{braced, Attribute, Ident, Path, Signature, Visibility};
// syn::AttributeArgs does not implement syn::Parse
type AttributeArgs = syn::punctuated::Punctuated<syn::NestedMeta, syn::Token![,]>;
type AttributeArgs = syn::punctuated::Punctuated<syn::Meta, syn::Token![,]>;
#[derive(Clone, Copy, PartialEq)]
enum RuntimeFlavor {
@@ -29,6 +29,7 @@ struct FinalConfig {
flavor: RuntimeFlavor,
worker_threads: Option<usize>,
start_paused: Option<bool>,
crate_name: Option<Path>,
}
/// Config used in case of the attribute not being able to build a valid config
@@ -36,6 +37,7 @@ const DEFAULT_ERROR_CONFIG: FinalConfig = FinalConfig {
flavor: RuntimeFlavor::CurrentThread,
worker_threads: None,
start_paused: None,
crate_name: None,
};
struct Configuration {
@@ -45,6 +47,7 @@ struct Configuration {
worker_threads: Option<(usize, Span)>,
start_paused: Option<(bool, Span)>,
is_test: bool,
crate_name: Option<Path>,
}
impl Configuration {
@@ -59,6 +62,7 @@ impl Configuration {
worker_threads: None,
start_paused: None,
is_test,
crate_name: None,
}
}
@@ -104,6 +108,15 @@ impl Configuration {
Ok(())
}
fn set_crate_name(&mut self, name: syn::Lit, span: Span) -> Result<(), syn::Error> {
if self.crate_name.is_some() {
return Err(syn::Error::new(span, "`crate` set multiple times."));
}
let name_path = parse_path(name, span, "crate")?;
self.crate_name = Some(name_path);
Ok(())
}
fn macro_name(&self) -> &'static str {
if self.is_test {
"tokio::test"
@@ -151,6 +164,7 @@ impl Configuration {
};
Ok(FinalConfig {
crate_name: self.crate_name.clone(),
flavor,
worker_threads,
start_paused,
@@ -185,6 +199,26 @@ fn parse_string(int: syn::Lit, span: Span, field: &str) -> Result<String, syn::E
}
}
fn parse_path(lit: syn::Lit, span: Span, field: &str) -> Result<Path, syn::Error> {
match lit {
syn::Lit::Str(s) => {
let err = syn::Error::new(
span,
format!(
"Failed to parse value of `{}` as path: \"{}\"",
field,
s.value()
),
);
s.parse::<syn::Path>().map_err(|_| err.clone())
}
_ => Err(syn::Error::new(
span,
format!("Failed to parse value of `{}` as path.", field),
)),
}
}
fn parse_bool(bool: syn::Lit, span: Span, field: &str) -> Result<bool, syn::Error> {
match bool {
syn::Lit::Bool(b) => Ok(b.value),
@@ -196,7 +230,7 @@ fn parse_bool(bool: syn::Lit, span: Span, field: &str) -> Result<bool, syn::Erro
}
fn build_config(
input: syn::ItemFn,
input: &ItemFn,
args: AttributeArgs,
is_test: bool,
rt_multi_thread: bool,
@@ -211,7 +245,7 @@ fn build_config(
for arg in args {
match arg {
syn::NestedMeta::Meta(syn::Meta::NameValue(namevalue)) => {
syn::Meta::NameValue(namevalue) => {
let ident = namevalue
.path
.get_ident()
@@ -220,39 +254,37 @@ fn build_config(
})?
.to_string()
.to_lowercase();
let lit = match &namevalue.value {
syn::Expr::Lit(syn::ExprLit { lit, .. }) => lit,
expr => return Err(syn::Error::new_spanned(expr, "Must be a literal")),
};
match ident.as_str() {
"worker_threads" => {
config.set_worker_threads(
namevalue.lit.clone(),
syn::spanned::Spanned::span(&namevalue.lit),
)?;
config.set_worker_threads(lit.clone(), syn::spanned::Spanned::span(lit))?;
}
"flavor" => {
config.set_flavor(
namevalue.lit.clone(),
syn::spanned::Spanned::span(&namevalue.lit),
)?;
config.set_flavor(lit.clone(), syn::spanned::Spanned::span(lit))?;
}
"start_paused" => {
config.set_start_paused(
namevalue.lit.clone(),
syn::spanned::Spanned::span(&namevalue.lit),
)?;
config.set_start_paused(lit.clone(), syn::spanned::Spanned::span(lit))?;
}
"core_threads" => {
let msg = "Attribute `core_threads` is renamed to `worker_threads`";
return Err(syn::Error::new_spanned(namevalue, msg));
}
"crate" => {
config.set_crate_name(lit.clone(), syn::spanned::Spanned::span(lit))?;
}
name => {
let msg = format!(
"Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`",
"Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`",
name,
);
return Err(syn::Error::new_spanned(namevalue, msg));
}
}
}
syn::NestedMeta::Meta(syn::Meta::Path(path)) => {
syn::Meta::Path(path) => {
let name = path
.get_ident()
.ok_or_else(|| syn::Error::new_spanned(&path, "Must have specified ident"))?
@@ -275,7 +307,7 @@ fn build_config(
format!("The `{}` attribute requires an argument.", name)
}
name => {
format!("Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`", name)
format!("Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`", name)
}
};
return Err(syn::Error::new_spanned(path, msg));
@@ -292,18 +324,13 @@ fn build_config(
config.build()
}
fn parse_knobs(mut input: syn::ItemFn, is_test: bool, config: FinalConfig) -> TokenStream {
fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenStream {
input.sig.asyncness = None;
// If type mismatch occurs, the current rustc points to the last statement.
let (last_stmt_start_span, last_stmt_end_span) = {
let mut last_stmt = input
.block
.stmts
.last()
.map(ToTokens::into_token_stream)
.unwrap_or_default()
.into_iter();
let mut last_stmt = input.stmts.last().cloned().unwrap_or_default().into_iter();
// `Span` on stable Rust has a limitation that only points to the first
// token, not the whole tokens. We can work around this limitation by
// using the first/last span of the tokens like
@@ -313,19 +340,24 @@ fn parse_knobs(mut input: syn::ItemFn, is_test: bool, config: FinalConfig) -> To
(start, end)
};
let crate_path = config
.crate_name
.map(ToTokens::into_token_stream)
.unwrap_or_else(|| Ident::new("tokio", last_stmt_start_span).into_token_stream());
let mut rt = match config.flavor {
RuntimeFlavor::CurrentThread => quote_spanned! {last_stmt_start_span=>
tokio::runtime::Builder::new_current_thread()
#crate_path::runtime::Builder::new_current_thread()
},
RuntimeFlavor::Threaded => quote_spanned! {last_stmt_start_span=>
tokio::runtime::Builder::new_multi_thread()
#crate_path::runtime::Builder::new_multi_thread()
},
};
if let Some(v) = config.worker_threads {
rt = quote! { #rt.worker_threads(#v) };
rt = quote_spanned! {last_stmt_start_span=> #rt.worker_threads(#v) };
}
if let Some(v) = config.start_paused {
rt = quote! { #rt.start_paused(#v) };
rt = quote_spanned! {last_stmt_start_span=> #rt.start_paused(#v) };
}
let header = if is_test {
@@ -336,46 +368,53 @@ fn parse_knobs(mut input: syn::ItemFn, is_test: bool, config: FinalConfig) -> To
quote! {}
};
let body = &input.block;
let brace_token = input.block.brace_token;
let (tail_return, tail_semicolon) = match body.stmts.last() {
Some(syn::Stmt::Semi(expr, _)) => match expr {
syn::Expr::Return(_) => (quote! { return }, quote! { ; }),
_ => match &input.sig.output {
syn::ReturnType::Type(_, ty) if matches!(&**ty, syn::Type::Tuple(ty) if ty.elems.is_empty()) =>
{
(quote! {}, quote! { ; }) // unit
}
syn::ReturnType::Default => (quote! {}, quote! { ; }), // unit
syn::ReturnType::Type(..) => (quote! {}, quote! {}), // ! or another
},
},
_ => (quote! {}, quote! {}),
};
input.block = syn::parse2(quote_spanned! {last_stmt_end_span=>
let body_ident = quote! { body };
let last_block = quote_spanned! {last_stmt_end_span=>
#[allow(clippy::expect_used, clippy::diverging_sub_expression)]
{
let body = async #body;
#[allow(clippy::expect_used)]
#tail_return #rt
return #rt
.enable_all()
.build()
.expect("Failed building the Runtime")
.block_on(body)#tail_semicolon
.block_on(#body_ident);
}
})
.expect("Parsing failure");
input.block.brace_token = brace_token;
let result = quote! {
#header
#input
};
result.into()
let body = input.body();
// For test functions pin the body to the stack and use `Pin<&mut dyn
// Future>` to reduce the amount of `Runtime::block_on` (and related
// functions) copies we generate during compilation due to the generic
// parameter `F` (the future to block on). This could have an impact on
// performance, but because it's only for testing it's unlikely to be very
// large.
//
// We don't do this for the main function as it should only be used once so
// there will be no benefit.
let body = if is_test {
let output_type = match &input.sig.output {
// For functions with no return value syn doesn't print anything,
// but that doesn't work as `Output` for our boxed `Future`, so
// default to `()` (the same type as the function output).
syn::ReturnType::Default => quote! { () },
syn::ReturnType::Type(_, ret_type) => quote! { #ret_type },
};
quote! {
let body = async #body;
#crate_path::pin!(body);
let body: ::std::pin::Pin<&mut dyn ::std::future::Future<Output = #output_type>> = body;
}
} else {
quote! {
let body = async #body;
}
};
input.into_tokens(header, body, last_block)
}
fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
tokens.extend(TokenStream::from(error.into_compile_error()));
tokens.extend(error.into_compile_error());
tokens
}
@@ -384,7 +423,7 @@ pub(crate) fn main(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
// If any of the steps for this macro fail, we still want to expand to an item that is as close
// to the expected output as possible. This helps out IDEs such that completions and other
// related features keep working.
let input: syn::ItemFn = match syn::parse(item.clone()) {
let input: ItemFn = match syn::parse2(item.clone()) {
Ok(it) => it,
Err(e) => return token_stream_with_error(item, e),
};
@@ -394,8 +433,8 @@ pub(crate) fn main(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
Err(syn::Error::new_spanned(&input.sig.ident, msg))
} else {
AttributeArgs::parse_terminated
.parse(args)
.and_then(|args| build_config(input.clone(), args, false, rt_multi_thread))
.parse2(args)
.and_then(|args| build_config(&input, args, false, rt_multi_thread))
};
match config {
@@ -408,17 +447,17 @@ pub(crate) fn test(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
// If any of the steps for this macro fail, we still want to expand to an item that is as close
// to the expected output as possible. This helps out IDEs such that completions and other
// related features keep working.
let input: syn::ItemFn = match syn::parse(item.clone()) {
let input: ItemFn = match syn::parse2(item.clone()) {
Ok(it) => it,
Err(e) => return token_stream_with_error(item, e),
};
let config = if let Some(attr) = input.attrs.iter().find(|attr| attr.path.is_ident("test")) {
let config = if let Some(attr) = input.attrs().find(|attr| attr.meta.path().is_ident("test")) {
let msg = "second test attribute is supplied";
Err(syn::Error::new_spanned(&attr, msg))
Err(syn::Error::new_spanned(attr, msg))
} else {
AttributeArgs::parse_terminated
.parse(args)
.and_then(|args| build_config(input.clone(), args, true, rt_multi_thread))
.parse2(args)
.and_then(|args| build_config(&input, args, true, rt_multi_thread))
};
match config {
@@ -426,3 +465,127 @@ pub(crate) fn test(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
Err(e) => token_stream_with_error(parse_knobs(input, true, DEFAULT_ERROR_CONFIG), e),
}
}
struct ItemFn {
outer_attrs: Vec<Attribute>,
vis: Visibility,
sig: Signature,
brace_token: syn::token::Brace,
inner_attrs: Vec<Attribute>,
stmts: Vec<proc_macro2::TokenStream>,
}
impl ItemFn {
/// Access all attributes of the function item.
fn attrs(&self) -> impl Iterator<Item = &Attribute> {
self.outer_attrs.iter().chain(self.inner_attrs.iter())
}
/// Get the body of the function item in a manner so that it can be
/// conveniently used with the `quote!` macro.
fn body(&self) -> Body<'_> {
Body {
brace_token: self.brace_token,
stmts: &self.stmts,
}
}
/// Convert our local function item into a token stream.
fn into_tokens(
self,
header: proc_macro2::TokenStream,
body: proc_macro2::TokenStream,
last_block: proc_macro2::TokenStream,
) -> TokenStream {
let mut tokens = proc_macro2::TokenStream::new();
header.to_tokens(&mut tokens);
// Outer attributes are simply streamed as-is.
for attr in self.outer_attrs {
attr.to_tokens(&mut tokens);
}
// Inner attributes require extra care, since they're not supported on
// blocks (which is what we're expanded into) we instead lift them
// outside of the function. This matches the behaviour of `syn`.
for mut attr in self.inner_attrs {
attr.style = syn::AttrStyle::Outer;
attr.to_tokens(&mut tokens);
}
self.vis.to_tokens(&mut tokens);
self.sig.to_tokens(&mut tokens);
self.brace_token.surround(&mut tokens, |tokens| {
body.to_tokens(tokens);
last_block.to_tokens(tokens);
});
tokens
}
}
impl Parse for ItemFn {
#[inline]
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
// This parse implementation has been largely lifted from `syn`, with
// the exception of:
// * We don't have access to the plumbing necessary to parse inner
// attributes in-place.
// * We do our own statements parsing to avoid recursively parsing
// entire statements and only look for the parts we're interested in.
let outer_attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let sig: Signature = input.parse()?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = Attribute::parse_inner(&content)?;
let mut buf = proc_macro2::TokenStream::new();
let mut stmts = Vec::new();
while !content.is_empty() {
if let Some(semi) = content.parse::<Option<syn::Token![;]>>()? {
semi.to_tokens(&mut buf);
stmts.push(buf);
buf = proc_macro2::TokenStream::new();
continue;
}
// Parse a single token tree and extend our current buffer with it.
// This avoids parsing the entire content of the sub-tree.
buf.extend([content.parse::<TokenTree>()?]);
}
if !buf.is_empty() {
stmts.push(buf);
}
Ok(Self {
outer_attrs,
vis,
sig,
brace_token,
inner_attrs,
stmts,
})
}
}
struct Body<'a> {
brace_token: syn::token::Brace,
// Statements, with terminating `;`.
stmts: &'a [TokenStream],
}
impl ToTokens for Body<'_> {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
self.brace_token.surround(tokens, |tokens| {
for stmt in self.stmts {
stmt.to_tokens(tokens);
}
})
}
}
+191 -33
View File
@@ -5,7 +5,6 @@
rust_2018_idioms,
unreachable_pub
)]
#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
@@ -40,6 +39,13 @@ use proc_macro::TokenStream;
/// function is called often, it is preferable to create the runtime using the
/// runtime builder so the runtime can be reused across calls.
///
/// # Non-worker async function
///
/// Note that the async function marked with this macro does not run as a
/// worker. The expectation is that other tasks are spawned by the function here.
/// Awaiting on other futures from the function provided here will not
/// perform as fast as those spawned as workers.
///
/// # Multi-threaded runtime
///
/// To use the multi-threaded runtime, the macro can be configured using
@@ -169,21 +175,41 @@ use proc_macro::TokenStream;
///
/// Note that `start_paused` requires the `test-util` feature to be enabled.
///
/// ### NOTE:
/// ### Rename package
///
/// If you rename the Tokio crate in your dependencies this macro will not work.
/// If you must rename the current version of Tokio because you're also using an
/// older version of Tokio, you _must_ make the current version of Tokio
/// available as `tokio` in the module where this macro is expanded.
/// ```rust
/// use tokio as tokio1;
///
/// #[tokio1::main(crate = "tokio1")]
/// async fn main() {
/// println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// use tokio as tokio1;
///
/// fn main() {
/// tokio1::runtime::Builder::new_multi_thread()
/// .enable_all()
/// .build()
/// .unwrap()
/// .block_on(async {
/// println!("Hello world");
/// })
/// }
/// ```
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
entry::main(args, item, true)
entry::main(args.into(), item.into(), true).into()
}
/// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
/// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
/// [Builder](../tokio/runtime/struct.builder.html) directly.
/// [Builder](../tokio/runtime/struct.Builder.html) directly.
///
/// ## Function arguments:
///
@@ -214,23 +240,52 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
/// }
/// ```
///
/// ### NOTE:
/// ### Rename package
///
/// If you rename the Tokio crate in your dependencies this macro will not work.
/// If you must rename the current version of Tokio because you're also using an
/// older version of Tokio, you _must_ make the current version of Tokio
/// available as `tokio` in the module where this macro is expanded.
/// ```rust
/// use tokio as tokio1;
///
/// #[tokio1::main(crate = "tokio1")]
/// async fn main() {
/// println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// use tokio as tokio1;
///
/// fn main() {
/// tokio1::runtime::Builder::new_multi_thread()
/// .enable_all()
/// .build()
/// .unwrap()
/// .block_on(async {
/// println!("Hello world");
/// })
/// }
/// ```
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
entry::main(args, item, false)
entry::main(args.into(), item.into(), false).into()
}
/// Marks async function to be executed by runtime, suitable to test environment
/// Marks async function to be executed by runtime, suitable to test environment.
/// This macro helps set up a `Runtime` without requiring the user to use
/// [Runtime](../tokio/runtime/struct.Runtime.html) or
/// [Builder](../tokio/runtime/struct.Builder.html) directly.
///
/// ## Usage
/// Note: This macro is designed to be simplistic and targets applications that
/// do not require a complex setup. If the provided functionality is not
/// sufficient, you may be interested in using
/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
/// powerful interface.
///
/// ### Multi-thread runtime
/// # Multi-threaded runtime
///
/// To use the multi-threaded runtime, the macro can be configured using
///
/// ```no_run
/// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
@@ -239,9 +294,16 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
/// }
/// ```
///
/// ### Using default
/// The `worker_threads` option configures the number of worker threads, and
/// defaults to the number of cpus on the system.
///
/// The default test runtime is single-threaded.
/// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
/// flag.
///
/// # Current thread runtime
///
/// The default test runtime is single-threaded. Each test gets a
/// separate current-thread runtime.
///
/// ```no_run
/// #[tokio::test]
@@ -250,6 +312,81 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
/// }
/// ```
///
/// ## Usage
///
/// ### Using the multi-thread runtime
///
/// ```no_run
/// #[tokio::test(flavor = "multi_thread")]
/// async fn my_test() {
/// assert!(true);
/// }
/// ```
///
/// Equivalent code not using `#[tokio::test]`
///
/// ```no_run
/// #[test]
/// fn my_test() {
/// tokio::runtime::Builder::new_multi_thread()
/// .enable_all()
/// .build()
/// .unwrap()
/// .block_on(async {
/// assert!(true);
/// })
/// }
/// ```
///
/// ### Using current thread runtime
///
/// ```no_run
/// #[tokio::test]
/// async fn my_test() {
/// assert!(true);
/// }
/// ```
///
/// Equivalent code not using `#[tokio::test]`
///
/// ```no_run
/// #[test]
/// fn my_test() {
/// tokio::runtime::Builder::new_current_thread()
/// .enable_all()
/// .build()
/// .unwrap()
/// .block_on(async {
/// assert!(true);
/// })
/// }
/// ```
///
/// ### Set number of worker threads
///
/// ```no_run
/// #[tokio::test(flavor ="multi_thread", worker_threads = 2)]
/// async fn my_test() {
/// assert!(true);
/// }
/// ```
///
/// Equivalent code not using `#[tokio::test]`
///
/// ```no_run
/// #[test]
/// fn my_test() {
/// tokio::runtime::Builder::new_multi_thread()
/// .worker_threads(2)
/// .enable_all()
/// .build()
/// .unwrap()
/// .block_on(async {
/// assert!(true);
/// })
/// }
/// ```
///
/// ### Configure the runtime to start with time paused
///
/// ```no_run
@@ -259,17 +396,37 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
/// }
/// ```
///
/// Equivalent code not using `#[tokio::test]`
///
/// ```no_run
/// #[test]
/// fn my_test() {
/// tokio::runtime::Builder::new_current_thread()
/// .enable_all()
/// .start_paused(true)
/// .build()
/// .unwrap()
/// .block_on(async {
/// assert!(true);
/// })
/// }
/// ```
///
/// Note that `start_paused` requires the `test-util` feature to be enabled.
///
/// ### NOTE:
/// ### Rename package
///
/// If you rename the Tokio crate in your dependencies this macro will not work.
/// If you must rename the current version of Tokio because you're also using an
/// older version of Tokio, you _must_ make the current version of Tokio
/// available as `tokio` in the module where this macro is expanded.
/// ```rust
/// use tokio as tokio1;
///
/// #[tokio1::test(crate = "tokio1")]
/// async fn my_test() {
/// println!("Hello world");
/// }
/// ```
#[proc_macro_attribute]
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
entry::test(args, item, true)
entry::test(args.into(), item.into(), true).into()
}
/// Marks async function to be executed by runtime, suitable to test environment
@@ -282,16 +439,9 @@ pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
/// assert!(true);
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the Tokio crate in your dependencies this macro will not work.
/// If you must rename the current version of Tokio because you're also using an
/// older version of Tokio, you _must_ make the current version of Tokio
/// available as `tokio` in the module where this macro is expanded.
#[proc_macro_attribute]
pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
entry::test(args, item, false)
entry::test(args.into(), item.into(), false).into()
}
/// Always fails with the error message below.
@@ -329,3 +479,11 @@ pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
select::declare_output_enum(input)
}
/// Implementation detail of the `select!` macro. This macro is **not** intended
/// to be used as part of the public API and is permitted to change.
#[proc_macro]
#[doc(hidden)]
pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
select::clean_pattern_macro(input)
}
+67 -1
View File
@@ -1,7 +1,7 @@
use proc_macro::{TokenStream, TokenTree};
use proc_macro2::Span;
use quote::quote;
use syn::Ident;
use syn::{parse::Parser, Ident};
pub(crate) fn declare_output_enum(input: TokenStream) -> TokenStream {
// passed in is: `(_ _ _)` with one `_` per branch
@@ -41,3 +41,69 @@ pub(crate) fn declare_output_enum(input: TokenStream) -> TokenStream {
pub(super) type Mask = #mask;
})
}
pub(crate) fn clean_pattern_macro(input: TokenStream) -> TokenStream {
// If this isn't a pattern, we return the token stream as-is. The select!
// macro is using it in a location requiring a pattern, so an error will be
// emitted there.
let mut input: syn::Pat = match syn::Pat::parse_single.parse(input.clone()) {
Ok(it) => it,
Err(_) => return input,
};
clean_pattern(&mut input);
quote::ToTokens::into_token_stream(input).into()
}
// Removes any occurrences of ref or mut in the provided pattern.
fn clean_pattern(pat: &mut syn::Pat) {
match pat {
syn::Pat::Lit(_literal) => {}
syn::Pat::Macro(_macro) => {}
syn::Pat::Path(_path) => {}
syn::Pat::Range(_range) => {}
syn::Pat::Rest(_rest) => {}
syn::Pat::Verbatim(_tokens) => {}
syn::Pat::Wild(_underscore) => {}
syn::Pat::Ident(ident) => {
ident.by_ref = None;
ident.mutability = None;
if let Some((_at, pat)) = &mut ident.subpat {
clean_pattern(&mut *pat);
}
}
syn::Pat::Or(or) => {
for case in or.cases.iter_mut() {
clean_pattern(case);
}
}
syn::Pat::Slice(slice) => {
for elem in slice.elems.iter_mut() {
clean_pattern(elem);
}
}
syn::Pat::Struct(struct_pat) => {
for field in struct_pat.fields.iter_mut() {
clean_pattern(&mut field.pat);
}
}
syn::Pat::Tuple(tuple) => {
for elem in tuple.elems.iter_mut() {
clean_pattern(elem);
}
}
syn::Pat::TupleStruct(tuple) => {
for elem in tuple.elems.iter_mut() {
clean_pattern(elem);
}
}
syn::Pat::Reference(reference) => {
reference.mutability = None;
clean_pattern(&mut reference.pat);
}
syn::Pat::Type(type_pat) => {
clean_pattern(&mut type_pat.pat);
}
_ => {}
}
}
+73
View File
@@ -1,3 +1,76 @@
# 0.1.14 (April 26th, 2023)
This bugfix release bumps the minimum version of Tokio to 1.15, which is
necessary for `timeout_repeating` to compile. ([#5657])
[#5657]: https://github.com/tokio-rs/tokio/pull/5657
# 0.1.13 (April 25th, 2023)
This release bumps the MSRV of tokio-stream to 1.56.
- stream: add "full" feature flag ([#5639])
- stream: add `StreamExt::timeout_repeating` ([#5577])
- stream: add `StreamNotifyClose` ([#4851])
[#4851]: https://github.com/tokio-rs/tokio/pull/4851
[#5577]: https://github.com/tokio-rs/tokio/pull/5577
[#5639]: https://github.com/tokio-rs/tokio/pull/5639
# 0.1.12 (January 20, 2023)
- time: remove `Unpin` bound on `Throttle` methods ([#5105])
- time: document that `throttle` operates on ms granularity ([#5101])
- sync: add `WatchStream::from_changes` ([#5432])
[#5105]: https://github.com/tokio-rs/tokio/pull/5105
[#5101]: https://github.com/tokio-rs/tokio/pull/5101
[#5432]: https://github.com/tokio-rs/tokio/pull/5432
# 0.1.11 (October 11, 2022)
- time: allow `StreamExt::chunks_timeout` outside of a runtime ([#5036])
[#5036]: https://github.com/tokio-rs/tokio/pull/5036
# 0.1.10 (Sept 18, 2022)
- time: add `StreamExt::chunks_timeout` ([#4695])
- stream: add track_caller to public APIs ([#4786])
[#4695]: https://github.com/tokio-rs/tokio/pull/4695
[#4786]: https://github.com/tokio-rs/tokio/pull/4786
# 0.1.9 (June 4, 2022)
- deps: upgrade `tokio-util` dependency to `0.7.x` ([#3762])
- stream: add `StreamExt::map_while` ([#4351])
- stream: add `StreamExt::then` ([#4355])
- stream: add cancel-safety docs to `StreamExt::next` and `try_next` ([#4715])
- stream: expose `Elapsed` error ([#4502])
- stream: expose `Timeout` ([#4601])
- stream: implement `Extend` for `StreamMap` ([#4272])
- sync: add `Clone` to `RecvError` types ([#4560])
[#3762]: https://github.com/tokio-rs/tokio/pull/3762
[#4272]: https://github.com/tokio-rs/tokio/pull/4272
[#4351]: https://github.com/tokio-rs/tokio/pull/4351
[#4355]: https://github.com/tokio-rs/tokio/pull/4355
[#4502]: https://github.com/tokio-rs/tokio/pull/4502
[#4560]: https://github.com/tokio-rs/tokio/pull/4560
[#4601]: https://github.com/tokio-rs/tokio/pull/4601
[#4715]: https://github.com/tokio-rs/tokio/pull/4715
# 0.1.8 (October 29, 2021)
- stream: add `From<Receiver<T>>` impl for receiver streams ([#4080])
- stream: impl `FromIterator` for `StreamMap` ([#4052])
- signal: make windows docs for signal module show up on unix builds ([#3770])
[#3770]: https://github.com/tokio-rs/tokio/pull/3770
[#4052]: https://github.com/tokio-rs/tokio/pull/4052
[#4080]: https://github.com/tokio-rs/tokio/pull/4080
# 0.1.7 (July 7, 2021)
### Fixed
+17 -10
View File
@@ -2,17 +2,15 @@
name = "tokio-stream"
# When releasing to crates.io:
# - Remove path dependencies
# - Update doc url
# - Cargo.toml
# - Update CHANGELOG.md.
# - Create "tokio-stream-0.1.x" git tag.
version = "0.1.7"
edition = "2018"
version = "0.1.14"
edition = "2021"
rust-version = "1.56"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://tokio.rs"
documentation = "https://docs.rs/tokio-stream/0.1.7/tokio_stream"
description = """
Utilities to work with `Stream` and `tokio`.
"""
@@ -20,6 +18,16 @@ categories = ["asynchronous"]
[features]
default = ["time"]
full = [
"time",
"net",
"io-util",
"fs",
"sync",
"signal"
]
time = ["tokio/time"]
net = ["tokio/net"]
io-util = ["tokio/io-util"]
@@ -29,18 +37,17 @@ signal = ["tokio/signal"]
[dependencies]
futures-core = { version = "0.3.0" }
pin-project-lite = "0.2.0"
tokio = { version = "1.8.0", path = "../tokio", features = ["sync"] }
tokio-util = { version = "0.6.3", path = "../tokio-util", optional = true }
pin-project-lite = "0.2.7"
tokio = { version = "1.15.0", path = "../tokio", features = ["sync"] }
tokio-util = { version = "0.7.0", path = "../tokio-util", optional = true }
[dev-dependencies]
tokio = { version = "1.2.0", path = "../tokio", features = ["full", "test-util"] }
async-stream = "0.3"
parking_lot = "0.12.0"
tokio-test = { path = "../tokio-test" }
futures = { version = "0.3", default-features = false }
proptest = "1"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2021 Tokio Contributors
Copyright (c) 2023 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
+4
View File
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
+29
View File
@@ -0,0 +1,29 @@
[package]
name = "tokio-stream-fuzz"
version = "0.0.0"
publish = false
edition = "2021"
[package.metadata]
cargo-fuzz = true
[dependencies]
libfuzzer-sys = "0.4"
tokio-test = { path = "../../tokio-test" }
[dependencies.tokio-stream]
path = ".."
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[profile.release]
debug = 1
[[bin]]
name = "fuzz_stream_map"
path = "fuzz_targets/fuzz_stream_map.rs"
test = false
doc = false
@@ -0,0 +1,72 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use std::pin::Pin;
use tokio_stream::{self as stream, Stream, StreamMap};
use tokio_test::{assert_pending, assert_ready, task};
macro_rules! assert_ready_none {
($($t:tt)*) => {
match assert_ready!($($t)*) {
None => {}
Some(v) => panic!("expected `None`, got `Some({:?})`", v),
}
};
}
fn pin_box<T: Stream<Item = U> + 'static, U>(s: T) -> Pin<Box<dyn Stream<Item = U>>> {
Box::pin(s)
}
fuzz_target!(|data: [bool; 64]| {
use std::task::{Context, Poll};
struct DidPoll<T> {
did_poll: bool,
inner: T,
}
impl<T: Stream + Unpin> Stream for DidPoll<T> {
type Item = T::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T::Item>> {
self.did_poll = true;
Pin::new(&mut self.inner).poll_next(cx)
}
}
// Try the test with each possible length.
for len in 0..data.len() {
let mut map = task::spawn(StreamMap::new());
let mut expect = 0;
for (i, is_empty) in data[..len].iter().copied().enumerate() {
let inner = if is_empty {
pin_box(stream::empty::<()>())
} else {
expect += 1;
pin_box(stream::pending::<()>())
};
let stream = DidPoll {
did_poll: false,
inner,
};
map.insert(i, stream);
}
if expect == 0 {
assert_ready_none!(map.poll_next());
} else {
assert_pending!(map.poll_next());
assert_eq!(expect, map.values().count());
for stream in map.values() {
assert!(stream.did_poll);
}
}
}
});
+12 -7
View File
@@ -10,7 +10,6 @@
unreachable_pub
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
@@ -64,12 +63,12 @@
//! [`tokio-util`] provides the [`StreamReader`] and [`ReaderStream`]
//! types when the io feature is enabled.
//!
//! [`tokio-util`]: https://docs.rs/tokio-util/0.4/tokio_util/codec/index.html
//! [`tokio::io`]: https://docs.rs/tokio/1.0/tokio/io/index.html
//! [`AsyncRead`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncRead.html
//! [`AsyncWrite`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncWrite.html
//! [`ReaderStream`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.ReaderStream.html
//! [`StreamReader`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.StreamReader.html
//! [`tokio-util`]: https://docs.rs/tokio-util/latest/tokio_util/codec/index.html
//! [`tokio::io`]: https://docs.rs/tokio/latest/tokio/io/index.html
//! [`AsyncRead`]: https://docs.rs/tokio/latest/tokio/io/trait.AsyncRead.html
//! [`AsyncWrite`]: https://docs.rs/tokio/latest/tokio/io/trait.AsyncWrite.html
//! [`ReaderStream`]: https://docs.rs/tokio-util/latest/tokio_util/io/struct.ReaderStream.html
//! [`StreamReader`]: https://docs.rs/tokio-util/latest/tokio_util/io/struct.StreamReader.html
#[macro_use]
mod macros;
@@ -78,6 +77,9 @@ pub mod wrappers;
mod stream_ext;
pub use stream_ext::{collect::FromStream, StreamExt};
cfg_time! {
pub use stream_ext::timeout::{Elapsed, Timeout};
}
mod empty;
pub use empty::{empty, Empty};
@@ -94,5 +96,8 @@ pub use pending::{pending, Pending};
mod stream_map;
pub use stream_map::StreamMap;
mod stream_close;
pub use stream_close::StreamNotifyClose;
#[doc(no_inline)]
pub use futures_core::Stream;
+93
View File
@@ -0,0 +1,93 @@
use crate::Stream;
use pin_project_lite::pin_project;
use std::pin::Pin;
use std::task::{Context, Poll};
pin_project! {
/// A `Stream` that wraps the values in an `Option`.
///
/// Whenever the wrapped stream yields an item, this stream yields that item
/// wrapped in `Some`. When the inner stream ends, then this stream first
/// yields a `None` item, and then this stream will also end.
///
/// # Example
///
/// Using `StreamNotifyClose` to handle closed streams with `StreamMap`.
///
/// ```
/// use tokio_stream::{StreamExt, StreamMap, StreamNotifyClose};
///
/// #[tokio::main]
/// async fn main() {
/// let mut map = StreamMap::new();
/// let stream = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// let stream2 = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// map.insert(0, stream);
/// map.insert(1, stream2);
/// while let Some((key, val)) = map.next().await {
/// match val {
/// Some(val) => println!("got {val:?} from stream {key:?}"),
/// None => println!("stream {key:?} closed"),
/// }
/// }
/// }
/// ```
#[must_use = "streams do nothing unless polled"]
pub struct StreamNotifyClose<S> {
#[pin]
inner: Option<S>,
}
}
impl<S> StreamNotifyClose<S> {
/// Create a new `StreamNotifyClose`.
pub fn new(stream: S) -> Self {
Self {
inner: Some(stream),
}
}
/// Get back the inner `Stream`.
///
/// Returns `None` if the stream has reached its end.
pub fn into_inner(self) -> Option<S> {
self.inner
}
}
impl<S> Stream for StreamNotifyClose<S>
where
S: Stream,
{
type Item = Option<S::Item>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
// We can't invoke poll_next after it ended, so we unset the inner stream as a marker.
match self
.as_mut()
.project()
.inner
.as_pin_mut()
.map(|stream| S::poll_next(stream, cx))
{
Some(Poll::Ready(Some(item))) => Poll::Ready(Some(Some(item))),
Some(Poll::Ready(None)) => {
self.project().inner.set(None);
Poll::Ready(Some(None))
}
Some(Poll::Pending) => Poll::Pending,
None => Poll::Ready(None),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if let Some(inner) = &self.inner {
// We always return +1 because when there's stream there's atleast one more item.
let (l, u) = inner.size_hint();
(l.saturating_add(1), u.and_then(|u| u.checked_add(1)))
} else {
(0, Some(0))
}
}
}
+287 -8
View File
@@ -1,3 +1,4 @@
use core::future::Future;
use futures_core::Stream;
mod all;
@@ -27,6 +28,9 @@ use fuse::Fuse;
mod map;
use map::Map;
mod map_while;
use map_while::MapWhile;
mod merge;
use merge::Merge;
@@ -39,21 +43,28 @@ use skip::Skip;
mod skip_while;
use skip_while::SkipWhile;
mod try_next;
use try_next::TryNext;
mod take;
use take::Take;
mod take_while;
use take_while::TakeWhile;
mod then;
use then::Then;
mod try_next;
use try_next::TryNext;
cfg_time! {
mod timeout;
pub(crate) mod timeout;
pub(crate) mod timeout_repeating;
use timeout::Timeout;
use tokio::time::Duration;
use timeout_repeating::TimeoutRepeating;
use tokio::time::{Duration, Interval};
mod throttle;
use throttle::{throttle, Throttle};
mod chunks_timeout;
use chunks_timeout::ChunksTimeout;
}
/// An extension trait for the [`Stream`] trait that provides a variety of
@@ -106,6 +117,12 @@ pub trait StreamExt: Stream {
/// pinning it to the stack using the `pin_mut!` macro from the `pin_utils`
/// crate.
///
/// # Cancel safety
///
/// This method is cancel safe. The returned future only
/// holds onto a reference to the underlying stream,
/// so dropping it will never lose a value.
///
/// # Examples
///
/// ```
@@ -142,6 +159,12 @@ pub trait StreamExt: Stream {
/// an [`Option<Result<T, E>>`](Option), making for easy use
/// with the [`?`](std::ops::Try) operator.
///
/// # Cancel safety
///
/// This method is cancel safe. The returned future only
/// holds onto a reference to the underlying stream,
/// so dropping it will never lose a value.
///
/// # Examples
///
/// ```
@@ -197,6 +220,93 @@ pub trait StreamExt: Stream {
Map::new(self, f)
}
/// Map this stream's items to a different type for as long as determined by
/// the provided closure. A stream of the target type will be returned,
/// which will yield elements until the closure returns `None`.
///
/// The provided closure is executed over all elements of this stream as
/// they are made available, until it returns `None`. It is executed inline
/// with calls to [`poll_next`](Stream::poll_next). Once `None` is returned,
/// the underlying stream will not be polled again.
///
/// Note that this function consumes the stream passed into it and returns a
/// wrapped version of it, similar to the [`Iterator::map_while`] method in the
/// standard library.
///
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// let stream = stream::iter(1..=10);
/// let mut stream = stream.map_while(|x| {
/// if x < 4 {
/// Some(x + 3)
/// } else {
/// None
/// }
/// });
/// assert_eq!(stream.next().await, Some(4));
/// assert_eq!(stream.next().await, Some(5));
/// assert_eq!(stream.next().await, Some(6));
/// assert_eq!(stream.next().await, None);
/// # }
/// ```
fn map_while<T, F>(self, f: F) -> MapWhile<Self, F>
where
F: FnMut(Self::Item) -> Option<T>,
Self: Sized,
{
MapWhile::new(self, f)
}
/// Maps this stream's items asynchronously to a different type, returning a
/// new stream of the resulting type.
///
/// The provided closure is executed over all elements of this stream as
/// they are made available, and the returned future is executed. Only one
/// future is executed at the time.
///
/// Note that this function consumes the stream passed into it and returns a
/// wrapped version of it, similar to the existing `then` methods in the
/// standard library.
///
/// Be aware that if the future is not `Unpin`, then neither is the `Stream`
/// returned by this method. To handle this, you can use `tokio::pin!` as in
/// the example below or put the stream in a `Box` with `Box::pin(stream)`.
///
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// async fn do_async_work(value: i32) -> i32 {
/// value + 3
/// }
///
/// let stream = stream::iter(1..=3);
/// let stream = stream.then(do_async_work);
///
/// tokio::pin!(stream);
///
/// assert_eq!(stream.next().await, Some(4));
/// assert_eq!(stream.next().await, Some(5));
/// assert_eq!(stream.next().await, Some(6));
/// # }
/// ```
fn then<F, Fut>(self, f: F) -> Then<Self, Fut, F>
where
F: FnMut(Self::Item) -> Fut,
Fut: Future,
Self: Sized,
{
Then::new(self, f)
}
/// Combine two streams into one by interleaving the output of both as it
/// is produced.
///
@@ -816,7 +926,9 @@ pub trait StreamExt: Stream {
/// If the wrapped stream yields a value before the deadline is reached, the
/// value is returned. Otherwise, an error is returned. The caller may decide
/// to continue consuming the stream and will eventually get the next source
/// stream value once it becomes available.
/// stream value once it becomes available. See
/// [`timeout_repeating`](StreamExt::timeout_repeating) for an alternative
/// where the timeouts will repeat.
///
/// # Notes
///
@@ -863,6 +975,25 @@ pub trait StreamExt: Stream {
/// assert_eq!(int_stream.try_next().await, Ok(None));
/// # }
/// ```
///
/// Once a timeout error is received, no further events will be received
/// unless the wrapped stream yields a value (timeouts do not repeat).
///
/// ```
/// # #[tokio::main(flavor = "current_thread", start_paused = true)]
/// # async fn main() {
/// use tokio_stream::{StreamExt, wrappers::IntervalStream};
/// use std::time::Duration;
/// let interval_stream = IntervalStream::new(tokio::time::interval(Duration::from_millis(100)));
/// let timeout_stream = interval_stream.timeout(Duration::from_millis(10));
/// tokio::pin!(timeout_stream);
///
/// // Only one timeout will be received between values in the source stream.
/// assert!(timeout_stream.try_next().await.is_ok());
/// assert!(timeout_stream.try_next().await.is_err(), "expected one timeout");
/// assert!(timeout_stream.try_next().await.is_ok(), "expected no more timeouts");
/// # }
/// ```
#[cfg(all(feature = "time"))]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn timeout(self, duration: Duration) -> Timeout<Self>
@@ -872,8 +1003,99 @@ pub trait StreamExt: Stream {
Timeout::new(self, duration)
}
/// Applies a per-item timeout to the passed stream.
///
/// `timeout_repeating()` takes an [`Interval`](tokio::time::Interval) that
/// controls the time each element of the stream has to complete before
/// timing out.
///
/// If the wrapped stream yields a value before the deadline is reached, the
/// value is returned. Otherwise, an error is returned. The caller may decide
/// to continue consuming the stream and will eventually get the next source
/// stream value once it becomes available. Unlike `timeout()`, if no value
/// becomes available before the deadline is reached, additional errors are
/// returned at the specified interval. See [`timeout`](StreamExt::timeout)
/// for an alternative where the timeouts do not repeat.
///
/// # Notes
///
/// This function consumes the stream passed into it and returns a
/// wrapped version of it.
///
/// Polling the returned stream will continue to poll the inner stream even
/// if one or more items time out.
///
/// # Examples
///
/// Suppose we have a stream `int_stream` that yields 3 numbers (1, 2, 3):
///
/// ```
/// # #[tokio::main]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
/// use std::time::Duration;
/// # let int_stream = stream::iter(1..=3);
///
/// let int_stream = int_stream.timeout_repeating(tokio::time::interval(Duration::from_secs(1)));
/// tokio::pin!(int_stream);
///
/// // When no items time out, we get the 3 elements in succession:
/// assert_eq!(int_stream.try_next().await, Ok(Some(1)));
/// assert_eq!(int_stream.try_next().await, Ok(Some(2)));
/// assert_eq!(int_stream.try_next().await, Ok(Some(3)));
/// assert_eq!(int_stream.try_next().await, Ok(None));
///
/// // If the second item times out, we get an error and continue polling the stream:
/// # let mut int_stream = stream::iter(vec![Ok(1), Err(()), Ok(2), Ok(3)]);
/// assert_eq!(int_stream.try_next().await, Ok(Some(1)));
/// assert!(int_stream.try_next().await.is_err());
/// assert_eq!(int_stream.try_next().await, Ok(Some(2)));
/// assert_eq!(int_stream.try_next().await, Ok(Some(3)));
/// assert_eq!(int_stream.try_next().await, Ok(None));
///
/// // If we want to stop consuming the source stream the first time an
/// // element times out, we can use the `take_while` operator:
/// # let int_stream = stream::iter(vec![Ok(1), Err(()), Ok(2), Ok(3)]);
/// let mut int_stream = int_stream.take_while(Result::is_ok);
///
/// assert_eq!(int_stream.try_next().await, Ok(Some(1)));
/// assert_eq!(int_stream.try_next().await, Ok(None));
/// # }
/// ```
///
/// Timeout errors will be continuously produced at the specified interval
/// until the wrapped stream yields a value.
///
/// ```
/// # #[tokio::main(flavor = "current_thread", start_paused = true)]
/// # async fn main() {
/// use tokio_stream::{StreamExt, wrappers::IntervalStream};
/// use std::time::Duration;
/// let interval_stream = IntervalStream::new(tokio::time::interval(Duration::from_millis(23)));
/// let timeout_stream = interval_stream.timeout_repeating(tokio::time::interval(Duration::from_millis(9)));
/// tokio::pin!(timeout_stream);
///
/// // Multiple timeouts will be received between values in the source stream.
/// assert!(timeout_stream.try_next().await.is_ok());
/// assert!(timeout_stream.try_next().await.is_err(), "expected one timeout");
/// assert!(timeout_stream.try_next().await.is_err(), "expected a second timeout");
/// // Will eventually receive another value from the source stream...
/// assert!(timeout_stream.try_next().await.is_ok(), "expected non-timeout");
/// # }
/// ```
#[cfg(all(feature = "time"))]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn timeout_repeating(self, interval: Interval) -> TimeoutRepeating<Self>
where
Self: Sized,
{
TimeoutRepeating::new(self, interval)
}
/// Slows down a stream by enforcing a delay between items.
///
/// The underlying timer behind this utility has a granularity of one millisecond.
///
/// # Example
///
/// Create a throttled stream.
@@ -899,6 +1121,63 @@ pub trait StreamExt: Stream {
{
throttle(duration, self)
}
/// Batches the items in the given stream using a maximum duration and size for each batch.
///
/// This stream returns the next batch of items in the following situations:
/// 1. The inner stream has returned at least `max_size` many items since the last batch.
/// 2. The time since the first item of a batch is greater than the given duration.
/// 3. The end of the stream is reached.
///
/// The length of the returned vector is never empty or greater than the maximum size. Empty batches
/// will not be emitted if no items are received upstream.
///
/// # Panics
///
/// This function panics if `max_size` is zero
///
/// # Example
///
/// ```rust
/// use std::time::Duration;
/// use tokio::time;
/// use tokio_stream::{self as stream, StreamExt};
/// use futures::FutureExt;
///
/// #[tokio::main]
/// # async fn _unused() {}
/// # #[tokio::main(flavor = "current_thread", start_paused = true)]
/// async fn main() {
/// let iter = vec![1, 2, 3, 4].into_iter();
/// let stream0 = stream::iter(iter);
///
/// let iter = vec![5].into_iter();
/// let stream1 = stream::iter(iter)
/// .then(move |n| time::sleep(Duration::from_secs(5)).map(move |_| n));
///
/// let chunk_stream = stream0
/// .chain(stream1)
/// .chunks_timeout(3, Duration::from_secs(2));
/// tokio::pin!(chunk_stream);
///
/// // a full batch was received
/// assert_eq!(chunk_stream.next().await, Some(vec![1,2,3]));
/// // deadline was reached before max_size was reached
/// assert_eq!(chunk_stream.next().await, Some(vec![4]));
/// // last element in the stream
/// assert_eq!(chunk_stream.next().await, Some(vec![5]));
/// }
/// ```
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
#[track_caller]
fn chunks_timeout(self, max_size: usize, duration: Duration) -> ChunksTimeout<Self>
where
Self: Sized,
{
assert!(max_size > 0, "`max_size` must be non-zero.");
ChunksTimeout::new(self, max_size, duration)
}
}
impl<St: ?Sized> StreamExt for St where St: Stream {}
@@ -906,10 +1185,10 @@ impl<St: ?Sized> StreamExt for St where St: Stream {}
/// Merge the size hints from two streams.
fn merge_size_hints(
(left_low, left_high): (usize, Option<usize>),
(right_low, right_hign): (usize, Option<usize>),
(right_low, right_high): (usize, Option<usize>),
) -> (usize, Option<usize>) {
let low = left_low.saturating_add(right_low);
let high = match (left_high, right_hign) {
let high = match (left_high, right_high) {
(Some(h1), Some(h2)) => h1.checked_add(h2),
_ => None,
};
@@ -0,0 +1,86 @@
use crate::stream_ext::Fuse;
use crate::Stream;
use tokio::time::{sleep, Sleep};
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use pin_project_lite::pin_project;
use std::time::Duration;
pin_project! {
/// Stream returned by the [`chunks_timeout`](super::StreamExt::chunks_timeout) method.
#[must_use = "streams do nothing unless polled"]
#[derive(Debug)]
pub struct ChunksTimeout<S: Stream> {
#[pin]
stream: Fuse<S>,
#[pin]
deadline: Option<Sleep>,
duration: Duration,
items: Vec<S::Item>,
cap: usize, // https://github.com/rust-lang/futures-rs/issues/1475
}
}
impl<S: Stream> ChunksTimeout<S> {
pub(super) fn new(stream: S, max_size: usize, duration: Duration) -> Self {
ChunksTimeout {
stream: Fuse::new(stream),
deadline: None,
duration,
items: Vec::with_capacity(max_size),
cap: max_size,
}
}
}
impl<S: Stream> Stream for ChunksTimeout<S> {
type Item = Vec<S::Item>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let mut me = self.as_mut().project();
loop {
match me.stream.as_mut().poll_next(cx) {
Poll::Pending => break,
Poll::Ready(Some(item)) => {
if me.items.is_empty() {
me.deadline.set(Some(sleep(*me.duration)));
me.items.reserve_exact(*me.cap);
}
me.items.push(item);
if me.items.len() >= *me.cap {
return Poll::Ready(Some(std::mem::take(me.items)));
}
}
Poll::Ready(None) => {
// Returning Some here is only correct because we fuse the inner stream.
let last = if me.items.is_empty() {
None
} else {
Some(std::mem::take(me.items))
};
return Poll::Ready(last);
}
}
}
if !me.items.is_empty() {
if let Some(deadline) = me.deadline.as_pin_mut() {
ready!(deadline.poll(cx));
}
return Poll::Ready(Some(std::mem::take(me.items)));
}
Poll::Pending
}
fn size_hint(&self) -> (usize, Option<usize>) {
let chunk_len = if self.items.is_empty() { 0 } else { 1 };
let (lower, upper) = self.stream.size_hint();
let lower = (lower / self.cap).saturating_add(chunk_len);
let upper = upper.and_then(|x| x.checked_add(chunk_len));
(lower, upper)
}
}
+5 -9
View File
@@ -66,17 +66,17 @@ where
use Poll::Ready;
loop {
let mut me = self.as_mut().project();
let me = self.as_mut().project();
let item = match ready!(me.stream.poll_next(cx)) {
Some(item) => item,
None => {
return Ready(U::finalize(sealed::Internal, &mut me.collection));
return Ready(U::finalize(sealed::Internal, me.collection));
}
};
if !U::extend(sealed::Internal, &mut me.collection, item) {
return Ready(U::finalize(sealed::Internal, &mut me.collection));
if !U::extend(sealed::Internal, me.collection, item) {
return Ready(U::finalize(sealed::Internal, me.collection));
}
}
}
@@ -195,11 +195,7 @@ where
} else {
let res = mem::replace(collection, Ok(U::initialize(sealed::Internal, 0, Some(0))));
if let Err(err) = res {
Err(err)
} else {
unreachable!();
}
Err(res.map(drop).unwrap_err())
}
}
}
+52
View File
@@ -0,0 +1,52 @@
use crate::Stream;
use core::fmt;
use core::pin::Pin;
use core::task::{Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
/// Stream for the [`map_while`](super::StreamExt::map_while) method.
#[must_use = "streams do nothing unless polled"]
pub struct MapWhile<St, F> {
#[pin]
stream: St,
f: F,
}
}
impl<St, F> fmt::Debug for MapWhile<St, F>
where
St: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MapWhile")
.field("stream", &self.stream)
.finish()
}
}
impl<St, F> MapWhile<St, F> {
pub(super) fn new(stream: St, f: F) -> Self {
MapWhile { stream, f }
}
}
impl<St, F, T> Stream for MapWhile<St, F>
where
St: Stream,
F: FnMut(St::Item) -> Option<T>,
{
type Item = T;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
let me = self.project();
let f = me.f;
me.stream.poll_next(cx).map(|opt| opt.and_then(f))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.stream.size_hint();
(0, upper)
}
}
+7
View File
@@ -8,6 +8,13 @@ use pin_project_lite::pin_project;
pin_project! {
/// Future for the [`next`](super::StreamExt::next) method.
///
/// # Cancel safety
///
/// This method is cancel safe. It only
/// holds onto a reference to the underlying stream,
/// so dropping it will never lose a value.
///
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Next<'a, St: ?Sized> {
+83
View File
@@ -0,0 +1,83 @@
use crate::Stream;
use core::fmt;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
/// Stream for the [`then`](super::StreamExt::then) method.
#[must_use = "streams do nothing unless polled"]
pub struct Then<St, Fut, F> {
#[pin]
stream: St,
#[pin]
future: Option<Fut>,
f: F,
}
}
impl<St, Fut, F> fmt::Debug for Then<St, Fut, F>
where
St: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Then")
.field("stream", &self.stream)
.finish()
}
}
impl<St, Fut, F> Then<St, Fut, F> {
pub(super) fn new(stream: St, f: F) -> Self {
Then {
stream,
future: None,
f,
}
}
}
impl<St, F, Fut> Stream for Then<St, Fut, F>
where
St: Stream,
Fut: Future,
F: FnMut(St::Item) -> Fut,
{
type Item = Fut::Output;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Fut::Output>> {
let mut me = self.project();
loop {
if let Some(future) = me.future.as_mut().as_pin_mut() {
match future.poll(cx) {
Poll::Ready(item) => {
me.future.set(None);
return Poll::Ready(Some(item));
}
Poll::Pending => return Poll::Pending,
}
}
match me.stream.as_mut().poll_next(cx) {
Poll::Ready(Some(item)) => {
me.future.set(Some((me.f)(item)));
}
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let future_len = usize::from(self.future.is_some());
let (lower, upper) = self.stream.size_hint();
let lower = lower.saturating_add(future_len);
let upper = upper.and_then(|upper| upper.checked_add(future_len));
(lower, upper)
}
}
+1 -3
View File
@@ -4,7 +4,6 @@ use crate::Stream;
use tokio::time::{Duration, Instant, Sleep};
use std::future::Future;
use std::marker::Unpin;
use std::pin::Pin;
use std::task::{self, Poll};
@@ -41,8 +40,7 @@ pin_project! {
}
}
// XXX: are these safe if `T: !Unpin`?
impl<T: Unpin> Throttle<T> {
impl<T> Throttle<T> {
/// Acquires a reference to the underlying stream that this combinator is
/// pulling from.
pub fn get_ref(&self) -> &T {
+2 -2
View File
@@ -23,8 +23,8 @@ pin_project! {
}
}
/// Error returned by `Timeout`.
#[derive(Debug, PartialEq)]
/// Error returned by `Timeout` and `TimeoutRepeating`.
#[derive(Debug, PartialEq, Eq)]
pub struct Elapsed(());
impl<S: Stream> Timeout<S> {
@@ -0,0 +1,56 @@
use crate::stream_ext::Fuse;
use crate::{Elapsed, Stream};
use tokio::time::Interval;
use core::pin::Pin;
use core::task::{Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
/// Stream returned by the [`timeout_repeating`](super::StreamExt::timeout_repeating) method.
#[must_use = "streams do nothing unless polled"]
#[derive(Debug)]
pub struct TimeoutRepeating<S> {
#[pin]
stream: Fuse<S>,
#[pin]
interval: Interval,
}
}
impl<S: Stream> TimeoutRepeating<S> {
pub(super) fn new(stream: S, interval: Interval) -> Self {
TimeoutRepeating {
stream: Fuse::new(stream),
interval,
}
}
}
impl<S: Stream> Stream for TimeoutRepeating<S> {
type Item = Result<S::Item, Elapsed>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let mut me = self.project();
match me.stream.poll_next(cx) {
Poll::Ready(v) => {
if v.is_some() {
me.interval.reset();
}
return Poll::Ready(v.map(Ok));
}
Poll::Pending => {}
};
ready!(me.interval.poll_tick(cx));
Poll::Ready(Some(Err(Elapsed::new())))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (lower, _) = self.stream.size_hint();
// The timeout stream may insert an error an infinite number of times.
(lower, None)
}
}
+6
View File
@@ -9,6 +9,12 @@ use pin_project_lite::pin_project;
pin_project! {
/// Future for the [`try_next`](super::StreamExt::try_next) method.
///
/// # Cancel safety
///
/// This method is cancel safe. It only
/// holds onto a reference to the underlying stream,
/// so dropping it will never lose a value.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct TryNext<'a, St: ?Sized> {
+40 -1
View File
@@ -42,10 +42,18 @@ use std::task::{Context, Poll};
/// to be merged, it may be advisable to use tasks sending values on a shared
/// [`mpsc`] channel.
///
/// # Notes
///
/// `StreamMap` removes finished streams automatically, without alerting the user.
/// In some scenarios, the caller would want to know on closed streams.
/// To do this, use [`StreamNotifyClose`] as a wrapper to your stream.
/// It will return None when the stream is closed.
///
/// [`StreamExt::merge`]: crate::StreamExt::merge
/// [`mpsc`]: https://docs.rs/tokio/1.0/tokio/sync/mpsc/index.html
/// [`pin!`]: https://docs.rs/tokio/1.0/tokio/macro.pin.html
/// [`Box::pin`]: std::boxed::Box::pin
/// [`StreamNotifyClose`]: crate::StreamNotifyClose
///
/// # Examples
///
@@ -170,6 +178,28 @@ use std::task::{Context, Poll};
/// }
/// }
/// ```
///
/// Using `StreamNotifyClose` to handle closed streams with `StreamMap`.
///
/// ```
/// use tokio_stream::{StreamExt, StreamMap, StreamNotifyClose};
///
/// #[tokio::main]
/// async fn main() {
/// let mut map = StreamMap::new();
/// let stream = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// let stream2 = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// map.insert(0, stream);
/// map.insert(1, stream2);
/// while let Some((key, val)) = map.next().await {
/// match val {
/// Some(val) => println!("got {val:?} from stream {key:?}"),
/// None => println!("stream {key:?} closed"),
/// }
/// }
/// }
/// ```
#[derive(Debug)]
pub struct StreamMap<K, V> {
/// Streams stored in the map
@@ -568,7 +598,7 @@ where
}
}
impl<K, V> std::iter::FromIterator<(K, V)> for StreamMap<K, V>
impl<K, V> FromIterator<(K, V)> for StreamMap<K, V>
where
K: Hash + Eq,
{
@@ -585,6 +615,15 @@ where
}
}
impl<K, V> Extend<(K, V)> for StreamMap<K, V> {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = (K, V)>,
{
self.entries.extend(iter);
}
}
mod rand {
use std::cell::Cell;
+2 -2
View File
@@ -14,11 +14,11 @@ use std::task::{Context, Poll};
/// [`Stream`]: trait@crate::Stream
#[cfg_attr(docsrs, doc(cfg(feature = "sync")))]
pub struct BroadcastStream<T> {
inner: ReusableBoxFuture<(Result<T, RecvError>, Receiver<T>)>,
inner: ReusableBoxFuture<'static, (Result<T, RecvError>, Receiver<T>)>,
}
/// An error returned from the inner stream of a [`BroadcastStream`].
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum BroadcastStreamRecvError {
/// The receiver lagged too far behind. Attempting to receive again will
/// return the oldest message still retained by the channel.
+33 -3
View File
@@ -10,8 +10,9 @@ use tokio::sync::watch::error::RecvError;
/// A wrapper around [`tokio::sync::watch::Receiver`] that implements [`Stream`].
///
/// This stream will always start by yielding the current value when the WatchStream is polled,
/// regardless of whether it was the initial value or sent afterwards.
/// This stream will start by yielding the current value when the WatchStream is polled,
/// regardless of whether it was the initial value or sent afterwards,
/// unless you use [`WatchStream<T>::from_changes`].
///
/// # Examples
///
@@ -40,6 +41,28 @@ use tokio::sync::watch::error::RecvError;
/// let (tx, rx) = watch::channel("hello");
/// let mut rx = WatchStream::new(rx);
///
/// // existing rx output with "hello" is ignored here
///
/// tx.send("goodbye").unwrap();
/// assert_eq!(rx.next().await, Some("goodbye"));
/// # }
/// ```
///
/// Example with [`WatchStream<T>::from_changes`]:
///
/// ```
/// # #[tokio::main]
/// # async fn main() {
/// use futures::future::FutureExt;
/// use tokio::sync::watch;
/// use tokio_stream::{StreamExt, wrappers::WatchStream};
///
/// let (tx, rx) = watch::channel("hello");
/// let mut rx = WatchStream::from_changes(rx);
///
/// // no output from rx is available at this point - let's check this:
/// assert!(rx.next().now_or_never().is_none());
///
/// tx.send("goodbye").unwrap();
/// assert_eq!(rx.next().await, Some("goodbye"));
/// # }
@@ -49,7 +72,7 @@ use tokio::sync::watch::error::RecvError;
/// [`Stream`]: trait@crate::Stream
#[cfg_attr(docsrs, doc(cfg(feature = "sync")))]
pub struct WatchStream<T> {
inner: ReusableBoxFuture<(Result<(), RecvError>, Receiver<T>)>,
inner: ReusableBoxFuture<'static, (Result<(), RecvError>, Receiver<T>)>,
}
async fn make_future<T: Clone + Send + Sync>(
@@ -66,6 +89,13 @@ impl<T: 'static + Clone + Send + Sync> WatchStream<T> {
inner: ReusableBoxFuture::new(async move { (Ok(()), rx) }),
}
}
/// Create a new `WatchStream` that waits for the value to be changed.
pub fn from_changes(rx: Receiver<T>) -> Self {
Self {
inner: ReusableBoxFuture::new(make_future(rx)),
}
}
}
impl<T: Clone + 'static + Send + Sync> Stream for WatchStream<T> {
+84
View File
@@ -0,0 +1,84 @@
#![warn(rust_2018_idioms)]
#![cfg(all(feature = "time", feature = "sync", feature = "io-util"))]
use tokio::time;
use tokio_stream::{self as stream, StreamExt};
use tokio_test::assert_pending;
use tokio_test::task;
use futures::FutureExt;
use std::time::Duration;
#[tokio::test(start_paused = true)]
async fn usage() {
let iter = vec![1, 2, 3].into_iter();
let stream0 = stream::iter(iter);
let iter = vec![4].into_iter();
let stream1 =
stream::iter(iter).then(move |n| time::sleep(Duration::from_secs(3)).map(move |_| n));
let chunk_stream = stream0
.chain(stream1)
.chunks_timeout(4, Duration::from_secs(2));
let mut chunk_stream = task::spawn(chunk_stream);
assert_pending!(chunk_stream.poll_next());
time::advance(Duration::from_secs(2)).await;
assert_eq!(chunk_stream.next().await, Some(vec![1, 2, 3]));
assert_pending!(chunk_stream.poll_next());
time::advance(Duration::from_secs(2)).await;
assert_eq!(chunk_stream.next().await, Some(vec![4]));
}
#[tokio::test(start_paused = true)]
async fn full_chunk_with_timeout() {
let iter = vec![1, 2].into_iter();
let stream0 = stream::iter(iter);
let iter = vec![3].into_iter();
let stream1 =
stream::iter(iter).then(move |n| time::sleep(Duration::from_secs(1)).map(move |_| n));
let iter = vec![4].into_iter();
let stream2 =
stream::iter(iter).then(move |n| time::sleep(Duration::from_secs(3)).map(move |_| n));
let chunk_stream = stream0
.chain(stream1)
.chain(stream2)
.chunks_timeout(3, Duration::from_secs(2));
let mut chunk_stream = task::spawn(chunk_stream);
assert_pending!(chunk_stream.poll_next());
time::advance(Duration::from_secs(2)).await;
assert_eq!(chunk_stream.next().await, Some(vec![1, 2, 3]));
assert_pending!(chunk_stream.poll_next());
time::advance(Duration::from_secs(2)).await;
assert_eq!(chunk_stream.next().await, Some(vec![4]));
}
#[tokio::test]
#[ignore]
async fn real_time() {
let iter = vec![1, 2, 3, 4].into_iter();
let stream0 = stream::iter(iter);
let iter = vec![5].into_iter();
let stream1 =
stream::iter(iter).then(move |n| time::sleep(Duration::from_secs(5)).map(move |_| n));
let chunk_stream = stream0
.chain(stream1)
.chunks_timeout(3, Duration::from_secs(2));
let mut chunk_stream = task::spawn(chunk_stream);
assert_eq!(chunk_stream.next().await, Some(vec![1, 2, 3]));
assert_eq!(chunk_stream.next().await, Some(vec![4]));
assert_eq!(chunk_stream.next().await, Some(vec![5]));
}
+11
View File
@@ -0,0 +1,11 @@
use tokio_stream::{StreamExt, StreamNotifyClose};
#[tokio::test]
async fn basic_usage() {
let mut stream = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
assert_eq!(stream.next().await, Some(Some(0)));
assert_eq!(stream.next().await, Some(Some(1)));
assert_eq!(stream.next().await, Some(None));
assert_eq!(stream.next().await, None);
}
+55
View File
@@ -0,0 +1,55 @@
#![warn(rust_2018_idioms)]
#![cfg(all(feature = "time", not(target_os = "wasi")))] // Wasi does not support panic recovery
use parking_lot::{const_mutex, Mutex};
use std::error::Error;
use std::panic;
use std::sync::Arc;
use tokio::time::Duration;
use tokio_stream::{self as stream, StreamExt};
fn test_panic<Func: FnOnce() + panic::UnwindSafe>(func: Func) -> Option<String> {
static PANIC_MUTEX: Mutex<()> = const_mutex(());
{
let _guard = PANIC_MUTEX.lock();
let panic_file: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
let prev_hook = panic::take_hook();
{
let panic_file = panic_file.clone();
panic::set_hook(Box::new(move |panic_info| {
let panic_location = panic_info.location().unwrap();
panic_file
.lock()
.clone_from(&Some(panic_location.file().to_string()));
}));
}
let result = panic::catch_unwind(func);
// Return to the previously set panic hook (maybe default) so that we get nice error
// messages in the tests.
panic::set_hook(prev_hook);
if result.is_err() {
panic_file.lock().clone()
} else {
None
}
}
}
#[test]
fn stream_chunks_timeout_panic_caller() -> Result<(), Box<dyn Error>> {
let panic_location_file = test_panic(|| {
let iter = vec![1, 2, 3].into_iter();
let stream0 = stream::iter(iter);
let _chunk_stream = stream0.chunks_timeout(0, Duration::from_secs(2));
});
// The panic location should be in this file
assert_eq!(&panic_location_file.unwrap(), file!());
Ok(())
}
-56
View File
@@ -325,62 +325,6 @@ fn one_ready_many_none() {
}
}
proptest::proptest! {
#[test]
fn fuzz_pending_complete_mix(kinds: Vec<bool>) {
use std::task::{Context, Poll};
struct DidPoll<T> {
did_poll: bool,
inner: T,
}
impl<T: Stream + Unpin> Stream for DidPoll<T> {
type Item = T::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>)
-> Poll<Option<T::Item>>
{
self.did_poll = true;
Pin::new(&mut self.inner).poll_next(cx)
}
}
for _ in 0..10 {
let mut map = task::spawn(StreamMap::new());
let mut expect = 0;
for (i, &is_empty) in kinds.iter().enumerate() {
let inner = if is_empty {
pin_box(stream::empty::<()>())
} else {
expect += 1;
pin_box(stream::pending::<()>())
};
let stream = DidPoll {
did_poll: false,
inner,
};
map.insert(i, stream);
}
if expect == 0 {
assert_ready_none!(map.poll_next());
} else {
assert_pending!(map.poll_next());
assert_eq!(expect, map.values().count());
for stream in map.values() {
assert!(stream.did_poll);
}
}
}
}
}
fn pin_box<T: Stream<Item = U> + 'static, U>(s: T) -> Pin<Box<dyn Stream<Item = U>>> {
Box::pin(s)
}
+2 -2
View File
@@ -1,10 +1,10 @@
#![cfg(feature = "full")]
#![cfg(all(feature = "time", feature = "sync", feature = "io-util"))]
use tokio::time::{self, sleep, Duration};
use tokio_stream::{self, StreamExt};
use tokio_test::*;
use futures::StreamExt as _;
use futures::stream;
async fn maybe_sleep(idx: i32) -> i32 {
if idx % 2 == 0 {
+1 -1
View File
@@ -1,5 +1,5 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "full")]
#![cfg(all(feature = "time", feature = "sync", feature = "io-util"))]
use tokio::time;
use tokio_stream::StreamExt;
+29 -1
View File
@@ -3,9 +3,11 @@
use tokio::sync::watch;
use tokio_stream::wrappers::WatchStream;
use tokio_stream::StreamExt;
use tokio_test::assert_pending;
use tokio_test::task::spawn;
#[tokio::test]
async fn message_not_twice() {
async fn watch_stream_message_not_twice() {
let (tx, rx) = watch::channel("hello");
let mut counter = 0;
@@ -27,3 +29,29 @@ async fn message_not_twice() {
drop(tx);
task.await.unwrap();
}
#[tokio::test]
async fn watch_stream_from_rx() {
let (tx, rx) = watch::channel("hello");
let mut stream = WatchStream::from(rx);
assert_eq!(stream.next().await.unwrap(), "hello");
tx.send("bye").unwrap();
assert_eq!(stream.next().await.unwrap(), "bye");
}
#[tokio::test]
async fn watch_stream_from_changes() {
let (tx, rx) = watch::channel("hello");
let mut stream = WatchStream::from_changes(rx);
assert_pending!(spawn(&mut stream).poll_next());
tx.send("bye").unwrap();
assert_eq!(stream.next().await.unwrap(), "bye");
}
+4 -6
View File
@@ -2,17 +2,15 @@
name = "tokio-test"
# When releasing to crates.io:
# - Remove path dependencies
# - Update doc url
# - Cargo.toml
# - Update CHANGELOG.md.
# - Create "tokio-test-0.4.x" git tag.
version = "0.4.2"
edition = "2018"
edition = "2021"
rust-version = "1.56"
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.4.2/tokio_test"
description = """
Testing utilities for Tokio- and futures-based code
"""
@@ -20,8 +18,8 @@ categories = ["asynchronous", "testing"]
[dependencies]
tokio = { version = "1.2.0", path = "../tokio", features = ["rt", "sync", "time", "test-util"] }
tokio-stream = { version = "0.1", path = "../tokio-stream" }
async-stream = "0.3"
tokio-stream = { version = "0.1.1", path = "../tokio-stream" }
async-stream = "0.3.3"
bytes = "1.0.0"
futures-core = "0.3.0"
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2021 Tokio Contributors
Copyright (c) 2023 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
+2
View File
@@ -310,6 +310,8 @@ impl Inner {
if now < until {
break;
} else {
self.waiting = None;
}
} else {
self.waiting = Some(Instant::now() + *dur);
-1
View File
@@ -4,7 +4,6 @@
rust_2018_idioms,
unreachable_pub
)]
#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
+1 -1
View File
@@ -260,7 +260,7 @@ macro_rules! assert_err {
}};
}
/// Asserts that an exact duration has elapsed since since the start instant ±1ms.
/// Asserts that an exact duration has elapsed since the start instant ±1ms.
///
/// ```rust
/// use tokio::time::{self, Instant};
+37 -8
View File
@@ -1,4 +1,29 @@
//! Futures task based helpers
//! Futures task based helpers to easily test futures and manually written futures.
//!
//! The [`Spawn`] type is used as a mock task harness that allows you to poll futures
//! without needing to setup pinning or context. Any future can be polled but if the
//! future requires the tokio async context you will need to ensure that you poll the
//! [`Spawn`] within a tokio context, this means that as long as you are inside the
//! runtime it will work and you can poll it via [`Spawn`].
//!
//! [`Spawn`] also supports [`Stream`] to call `poll_next` without pinning
//! or context.
//!
//! In addition to circumventing the need for pinning and context, [`Spawn`] also tracks
//! the amount of times the future/task was woken. This can be useful to track if some
//! leaf future notified the root task correctly.
//!
//! # Example
//!
//! ```
//! use tokio_test::task;
//!
//! let fut = async {};
//!
//! let mut task = task::spawn(fut);
//!
//! assert!(task.poll().is_ready(), "Task was not ready!");
//! ```
#![allow(clippy::mutex_atomic)]
@@ -11,7 +36,11 @@ use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
use tokio_stream::Stream;
/// TODO: dox
/// Spawn a future into a [`Spawn`] which wraps the future in a mocked executor.
///
/// This can be used to spawn a [`Future`] or a [`Stream`].
///
/// For more information, check the module docs.
pub fn spawn<T>(task: T) -> Spawn<T> {
Spawn {
task: MockTask::new(),
@@ -19,16 +48,14 @@ pub fn spawn<T>(task: T) -> Spawn<T> {
}
}
/// Future spawned on a mock task
/// Future spawned on a mock task that can be used to poll the future or stream
/// without needing pinning or context types.
#[derive(Debug)]
pub struct Spawn<T> {
task: MockTask,
future: Pin<Box<T>>,
}
/// Mock task
///
/// A mock task is able to intercept and track wake notifications.
#[derive(Debug, Clone)]
struct MockTask {
waker: Arc<ThreadWaker>,
@@ -91,7 +118,8 @@ impl<T: Unpin> ops::DerefMut for Spawn<T> {
}
impl<T: Future> Spawn<T> {
/// Polls a future
/// If `T` is a [`Future`] then poll it. This will handle pinning and the context
/// type for the future.
pub fn poll(&mut self) -> Poll<T::Output> {
let fut = self.future.as_mut();
self.task.enter(|cx| fut.poll(cx))
@@ -99,7 +127,8 @@ impl<T: Future> Spawn<T> {
}
impl<T: Stream> Spawn<T> {
/// Polls a stream
/// If `T` is a [`Stream`] then poll_next it. This will handle pinning and the context
/// type for the stream.
pub fn poll_next(&mut self) -> Poll<Option<T::Item>> {
let stream = self.future.as_mut();
self.task.enter(|cx| stream.poll_next(cx))
+63
View File
@@ -2,6 +2,7 @@
use std::io;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::time::{Duration, Instant};
use tokio_test::io::Builder;
#[tokio::test]
@@ -84,3 +85,65 @@ async fn mock_panics_write_data_left() {
use tokio_test::io::Builder;
Builder::new().write(b"write").build();
}
#[tokio::test(start_paused = true)]
async fn wait() {
const FIRST_WAIT: Duration = Duration::from_secs(1);
let mut mock = Builder::new()
.wait(FIRST_WAIT)
.read(b"hello ")
.read(b"world!")
.build();
let mut buf = [0; 256];
let start = Instant::now(); // record the time the read call takes
//
let n = mock.read(&mut buf).await.expect("read 1");
assert_eq!(&buf[..n], b"hello ");
println!("time elapsed after first read {:?}", start.elapsed());
let n = mock.read(&mut buf).await.expect("read 2");
assert_eq!(&buf[..n], b"world!");
println!("time elapsed after second read {:?}", start.elapsed());
// make sure the .wait() instruction worked
assert!(
start.elapsed() >= FIRST_WAIT,
"consuming the whole mock only took {}ms",
start.elapsed().as_millis()
);
}
#[tokio::test(start_paused = true)]
async fn multiple_wait() {
const FIRST_WAIT: Duration = Duration::from_secs(1);
const SECOND_WAIT: Duration = Duration::from_secs(1);
let mut mock = Builder::new()
.wait(FIRST_WAIT)
.read(b"hello ")
.wait(SECOND_WAIT)
.read(b"world!")
.build();
let mut buf = [0; 256];
let start = Instant::now(); // record the time it takes to consume the mock
let n = mock.read(&mut buf).await.expect("read 1");
assert_eq!(&buf[..n], b"hello ");
println!("time elapsed after first read {:?}", start.elapsed());
let n = mock.read(&mut buf).await.expect("read 2");
assert_eq!(&buf[..n], b"world!");
println!("time elapsed after second read {:?}", start.elapsed());
// make sure the .wait() instruction worked
assert!(
start.elapsed() >= FIRST_WAIT + SECOND_WAIT,
"consuming the whole mock only took {}ms",
start.elapsed().as_millis()
);
}
+177
View File
@@ -1,3 +1,180 @@
# 0.7.8 (April 25th, 2023)
This release bumps the MSRV of tokio-util to 1.56.
### Added
- time: add `DelayQueue::peek` ([#5569])
### Changed
This release contains one performance improvement:
- sync: try to lock the parent first in `CancellationToken` ([#5561])
### Fixed
- time: fix panic in `DelayQueue` ([#5630])
### Documented
- sync: improve `CancellationToken` doc on child tokens ([#5632])
[#5561]: https://github.com/tokio-rs/tokio/pull/5561
[#5569]: https://github.com/tokio-rs/tokio/pull/5569
[#5630]: https://github.com/tokio-rs/tokio/pull/5630
[#5632]: https://github.com/tokio-rs/tokio/pull/5632
# 0.7.7 (February 12, 2023)
This release reverts the removal of the `Encoder` bound on the `FramedParts`
constructor from [#5280] since it turned out to be a breaking change. ([#5450])
[#5450]: https://github.com/tokio-rs/tokio/pull/5450
# 0.7.6 (February 10, 2023)
This release fixes a compilation failure in 0.7.5 when it is used together with
Tokio version 1.21 and unstable features are enabled. ([#5445])
[#5445]: https://github.com/tokio-rs/tokio/pull/5445
# 0.7.5 (February 9, 2023)
This release fixes an accidental breaking change where `UnwindSafe` was
accidentally removed from `CancellationToken`.
### Added
- codec: add `Framed::backpressure_boundary` ([#5124])
- io: add `InspectReader` and `InspectWriter` ([#5033])
- io: add `tokio_util::io::{CopyToBytes, SinkWriter}` ([#5070], [#5436])
- io: impl `std::io::BufRead` on `SyncIoBridge` ([#5265])
- sync: add `PollSemaphore::poll_acquire_many` ([#5137])
- sync: add owned future for `CancellationToken` ([#5153])
- time: add `DelayQueue::try_remove` ([#5052])
### Fixed
- codec: fix `LengthDelimitedCodec` buffer over-reservation ([#4997])
- sync: impl `UnwindSafe` on `CancellationToken` ([#5438])
- util: remove `Encoder` bound on `FramedParts` constructor ([#5280])
### Documented
- io: add lines example for `StreamReader` ([#5145])
[#4997]: https://github.com/tokio-rs/tokio/pull/4997
[#5033]: https://github.com/tokio-rs/tokio/pull/5033
[#5052]: https://github.com/tokio-rs/tokio/pull/5052
[#5070]: https://github.com/tokio-rs/tokio/pull/5070
[#5124]: https://github.com/tokio-rs/tokio/pull/5124
[#5137]: https://github.com/tokio-rs/tokio/pull/5137
[#5145]: https://github.com/tokio-rs/tokio/pull/5145
[#5153]: https://github.com/tokio-rs/tokio/pull/5153
[#5265]: https://github.com/tokio-rs/tokio/pull/5265
[#5280]: https://github.com/tokio-rs/tokio/pull/5280
[#5436]: https://github.com/tokio-rs/tokio/pull/5436
[#5438]: https://github.com/tokio-rs/tokio/pull/5438
# 0.7.4 (September 8, 2022)
### Added
- io: add `SyncIoBridge::shutdown()` ([#4938])
- task: improve `LocalPoolHandle` ([#4680])
### Fixed
- util: add `track_caller` to public APIs ([#4785])
### Unstable
- task: fix compilation errors in `JoinMap` with Tokio v1.21.0 ([#4755])
- task: remove the unstable, deprecated `JoinMap::join_one` ([#4920])
[#4680]: https://github.com/tokio-rs/tokio/pull/4680
[#4755]: https://github.com/tokio-rs/tokio/pull/4755
[#4785]: https://github.com/tokio-rs/tokio/pull/4785
[#4920]: https://github.com/tokio-rs/tokio/pull/4920
[#4938]: https://github.com/tokio-rs/tokio/pull/4938
# 0.7.3 (June 4, 2022)
### Changed
- tracing: don't require default tracing features ([#4592])
- util: simplify implementation of `ReusableBoxFuture` ([#4675])
### Added (unstable)
- task: add `JoinMap` ([#4640], [#4697])
[#4592]: https://github.com/tokio-rs/tokio/pull/4592
[#4640]: https://github.com/tokio-rs/tokio/pull/4640
[#4675]: https://github.com/tokio-rs/tokio/pull/4675
[#4697]: https://github.com/tokio-rs/tokio/pull/4697
# 0.7.2 (May 14, 2022)
This release contains a rewrite of `CancellationToken` that fixes a memory leak. ([#4652])
[#4652]: https://github.com/tokio-rs/tokio/pull/4652
# 0.7.1 (February 21, 2022)
### Added
- codec: add `length_field_type` to `LengthDelimitedCodec` builder ([#4508])
- io: add `StreamReader::into_inner_with_chunk()` ([#4559])
### Changed
- switch from log to tracing ([#4539])
### Fixed
- sync: fix waker update condition in `CancellationToken` ([#4497])
- bumped tokio dependency to 1.6 to satisfy minimum requirements ([#4490])
[#4490]: https://github.com/tokio-rs/tokio/pull/4490
[#4497]: https://github.com/tokio-rs/tokio/pull/4497
[#4508]: https://github.com/tokio-rs/tokio/pull/4508
[#4539]: https://github.com/tokio-rs/tokio/pull/4539
[#4559]: https://github.com/tokio-rs/tokio/pull/4559
# 0.7.0 (February 9, 2022)
### Added
- task: add `spawn_pinned` ([#3370])
- time: add `shrink_to_fit` and `compact` methods to `DelayQueue` ([#4170])
- codec: improve `Builder::max_frame_length` docs ([#4352])
- codec: add mutable reference getters for codecs to pinned `Framed` ([#4372])
- net: add generic trait to combine `UnixListener` and `TcpListener` ([#4385])
- codec: implement `Framed::map_codec` ([#4427])
- codec: implement `Encoder<BytesMut>` for `BytesCodec` ([#4465])
### Changed
- sync: add lifetime parameter to `ReusableBoxFuture` ([#3762])
- sync: refactored `PollSender<T>` to fix a subtly broken `Sink<T>` implementation ([#4214])
- time: remove error case from the infallible `DelayQueue::poll_elapsed` ([#4241])
[#3370]: https://github.com/tokio-rs/tokio/pull/3370
[#4170]: https://github.com/tokio-rs/tokio/pull/4170
[#4352]: https://github.com/tokio-rs/tokio/pull/4352
[#4372]: https://github.com/tokio-rs/tokio/pull/4372
[#4385]: https://github.com/tokio-rs/tokio/pull/4385
[#4427]: https://github.com/tokio-rs/tokio/pull/4427
[#4465]: https://github.com/tokio-rs/tokio/pull/4465
[#3762]: https://github.com/tokio-rs/tokio/pull/3762
[#4214]: https://github.com/tokio-rs/tokio/pull/4214
[#4241]: https://github.com/tokio-rs/tokio/pull/4241
# 0.6.10 (May 14, 2021)
This is a backport for the memory leak in `CancellationToken` that was originally fixed in 0.7.2. ([#4652])
[#4652]: https://github.com/tokio-rs/tokio/pull/4652
# 0.6.9 (October 29, 2021)
### Added
+19 -14
View File
@@ -2,17 +2,15 @@
name = "tokio-util"
# When releasing to crates.io:
# - Remove path dependencies
# - Update doc url
# - Cargo.toml
# - Update CHANGELOG.md.
# - Create "tokio-util-0.6.x" git tag.
version = "0.6.9"
edition = "2018"
# - Create "tokio-util-0.7.x" git tag.
version = "0.7.8"
edition = "2021"
rust-version = "1.56"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
homepage = "https://tokio.rs"
documentation = "https://docs.rs/tokio-util/0.6.9/tokio_util"
description = """
Additional utilities for working with Tokio.
"""
@@ -27,25 +25,27 @@ full = ["codec", "compat", "io-util", "time", "net", "rt"]
net = ["tokio/net"]
compat = ["futures-io",]
codec = []
codec = ["tracing"]
time = ["tokio/time","slab"]
io = []
io-util = ["io", "tokio/rt", "tokio/io-util"]
rt = ["tokio/rt"]
rt = ["tokio/rt", "tokio/sync", "futures-util", "hashbrown"]
__docs_rs = ["futures-util"]
[dependencies]
tokio = { version = "1.0.0", path = "../tokio", features = ["sync"] }
tokio = { version = "1.22.0", path = "../tokio", features = ["sync"] }
bytes = "1.0.0"
futures-core = "0.3.0"
futures-sink = "0.3.0"
futures-io = { version = "0.3.0", optional = true }
futures-util = { version = "0.3.0", optional = true }
log = "0.4"
pin-project-lite = "0.2.0"
slab = { version = "0.4.1", optional = true } # Backs `DelayQueue`
pin-project-lite = "0.2.7"
slab = { version = "0.4.4", optional = true } # Backs `DelayQueue`
tracing = { version = "0.1.25", default-features = false, features = ["std"], optional = true }
[target.'cfg(tokio_unstable)'.dependencies]
hashbrown = { version = "0.12.0", optional = true }
[dev-dependencies]
tokio = { version = "1.0.0", path = "../tokio", features = ["full"] }
@@ -55,7 +55,12 @@ tokio-stream = { version = "0.1", path = "../tokio-stream" }
async-stream = "0.3.0"
futures = "0.3.0"
futures-test = "0.3.5"
parking_lot = "0.12.0"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
# enable unstable features in the documentation
rustdoc-args = ["--cfg", "docsrs", "--cfg", "tokio_unstable"]
# it's necessary to _also_ pass `--cfg tokio_unstable` to rustc, or else
# dependencies will not be enabled, and the docs build will fail.
rustc-args = ["--cfg", "docsrs", "--cfg", "tokio_unstable"]
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2021 Tokio Contributors
Copyright (c) 2023 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
+10
View File
@@ -74,3 +74,13 @@ impl Encoder<Bytes> for BytesCodec {
Ok(())
}
}
impl Encoder<BytesMut> for BytesCodec {
type Error = io::Error;
fn encode(&mut self, data: BytesMut, buf: &mut BytesMut) -> Result<(), io::Error> {
buf.reserve(data.len());
buf.put(data);
Ok(())
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ use std::io;
/// it's possible to temporarily read 0 bytes by reaching EOF.
///
/// In these cases `decode_eof` will be called until it signals
/// fullfillment of all closing frames by returning `Ok(None)`.
/// fulfillment of all closing frames by returning `Ok(None)`.
/// After that, repeated attempts to read from the [`Framed`] or [`FramedRead`]
/// will not invoke `decode` or `decode_eof` again, until data can be read
/// during a retry.
+39
View File
@@ -204,6 +204,35 @@ impl<T, U> Framed<T, U> {
&mut self.inner.codec
}
/// Maps the codec `U` to `C`, preserving the read and write buffers
/// wrapped by `Framed`.
///
/// Note that care should be taken to not tamper with the underlying codec
/// as it may corrupt the stream of frames otherwise being worked with.
pub fn map_codec<C, F>(self, map: F) -> Framed<T, C>
where
F: FnOnce(U) -> C,
{
// This could be potentially simplified once rust-lang/rust#86555 hits stable
let parts = self.into_parts();
Framed::from_parts(FramedParts {
io: parts.io,
codec: map(parts.codec),
read_buf: parts.read_buf,
write_buf: parts.write_buf,
_priv: (),
})
}
/// Returns a mutable reference to the underlying codec wrapped by
/// `Framed`.
///
/// Note that care should be taken to not tamper with the underlying codec
/// as it may corrupt the stream of frames otherwise being worked with.
pub fn codec_pin_mut(self: Pin<&mut Self>) -> &mut U {
self.project().inner.project().codec
}
/// Returns a reference to the read buffer.
pub fn read_buffer(&self) -> &BytesMut {
&self.inner.state.read.buffer
@@ -224,6 +253,16 @@ impl<T, U> Framed<T, U> {
&mut self.inner.state.write.buffer
}
/// Returns backpressure boundary
pub fn backpressure_boundary(&self) -> usize {
self.inner.state.write.backpressure_boundary
}
/// Updates backpressure boundary
pub fn set_backpressure_boundary(&mut self, boundary: usize) {
self.inner.state.write.backpressure_boundary = boundary;
}
/// Consumes the `Framed`, returning its underlying I/O stream.
///
/// Note that care should be taken to not tamper with the underlying stream
+10 -6
View File
@@ -7,12 +7,12 @@ use tokio::io::{AsyncRead, AsyncWrite};
use bytes::BytesMut;
use futures_core::ready;
use futures_sink::Sink;
use log::trace;
use pin_project_lite::pin_project;
use std::borrow::{Borrow, BorrowMut};
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use tracing::trace;
pin_project! {
#[derive(Debug)]
@@ -25,7 +25,6 @@ pin_project! {
}
const INITIAL_CAPACITY: usize = 8 * 1024;
const BACKPRESSURE_BOUNDARY: usize = INITIAL_CAPACITY;
#[derive(Debug)]
pub(crate) struct ReadFrame {
@@ -37,6 +36,7 @@ pub(crate) struct ReadFrame {
pub(crate) struct WriteFrame {
pub(crate) buffer: BytesMut,
pub(crate) backpressure_boundary: usize,
}
#[derive(Default)]
@@ -60,6 +60,7 @@ impl Default for WriteFrame {
fn default() -> Self {
Self {
buffer: BytesMut::with_capacity(INITIAL_CAPACITY),
backpressure_boundary: INITIAL_CAPACITY,
}
}
}
@@ -87,7 +88,10 @@ impl From<BytesMut> for WriteFrame {
buffer.reserve(INITIAL_CAPACITY - size);
}
Self { buffer }
Self {
buffer,
backpressure_boundary: INITIAL_CAPACITY,
}
}
}
@@ -256,7 +260,7 @@ where
type Error = U::Error;
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
if self.state.borrow().buffer.len() >= BACKPRESSURE_BOUNDARY {
if self.state.borrow().buffer.len() >= self.state.borrow().backpressure_boundary {
self.as_mut().poll_flush(cx)
} else {
Poll::Ready(Ok(()))
@@ -277,8 +281,8 @@ where
let mut pinned = self.project();
while !pinned.state.borrow_mut().buffer.is_empty() {
let WriteFrame { buffer } = pinned.state.borrow_mut();
trace!("writing; remaining={}", buffer.len());
let WriteFrame { buffer, .. } = pinned.state.borrow_mut();
trace!(remaining = buffer.len(), "writing;");
let n = ready!(poll_write_buf(pinned.inner.as_mut(), cx, buffer))?;
+26
View File
@@ -108,6 +108,32 @@ impl<T, D> FramedRead<T, D> {
&mut self.inner.codec
}
/// Maps the decoder `D` to `C`, preserving the read buffer
/// wrapped by `Framed`.
pub fn map_decoder<C, F>(self, map: F) -> FramedRead<T, C>
where
F: FnOnce(D) -> C,
{
// This could be potentially simplified once rust-lang/rust#86555 hits stable
let FramedImpl {
inner,
state,
codec,
} = self.inner;
FramedRead {
inner: FramedImpl {
inner,
state,
codec: map(codec),
},
}
}
/// Returns a mutable reference to the underlying decoder.
pub fn decoder_pin_mut(self: Pin<&mut Self>) -> &mut D {
self.project().inner.project().codec
}
/// Returns a reference to the read buffer.
pub fn read_buffer(&self) -> &BytesMut {
&self.inner.state.buffer

Some files were not shown because too many files have changed in this diff Show More