Compare commits

...
Author SHA1 Message Date
Alice Ryhl 0b31c2f73d chore: prepare tokio-util v0.7.13 (#7012) 2024-12-04 12:49:55 +01:00
Zettroke 129f9fc0c8 codec: fix incorrect handling of invalid utf-8 in LinesCodec::decode_eof (#7011) 2024-12-04 10:18:14 +00:00
Hayden Stainsby b5c227d51f tracing: move tracing instrumentation tests into tokio tests (#7007)
In #6112, tests for the tracing instrumentation were introduced. They
had to live in their own test crate under `tokio/tests` because the
`tracing-mock` crate that the tests use had not yet been published to
crates.io.

Now `tracing-mock` has been published to crates.io and so the separate
test crate and separate job to run it are no longer necessary. The
tracing instrumentation tests can be placed in with the other
integration tests in the `tokio` crate.

The tests themselves have also been updated to match the changes in the
`tracing-mock` API since the version which was being used.
2024-12-04 07:47:48 +01:00
Alice Ryhl dcae2b9eb8 ci: unfreeze FreeBSD from rustc 1.81 (#7009) 2024-12-03 14:33:28 +00:00
Alice Ryhl bb9d57017e chore: prepare Tokio v1.42.0 (#7005) 2024-12-03 14:48:39 +01:00
leopardracer af9c683d52 tests: fix typo in build test instructions (#7004) 2024-12-03 13:11:36 +00:00
Alice Ryhl 4bc5a1a058 ci: allow Unicode-3.0 license for unicode-ident (#7006)
Signed-off-by: Alice Ryhl <[email protected]>
2024-12-03 13:57:31 +01:00
quininer f8948ea021 runtime: do not defer yield_now inside block_in_place (#6999) 2024-12-02 13:52:00 +01:00
David Herberth bce9780dd3 time: use array::from_fn instead of manually creating array (#7000) 2024-12-01 19:54:30 +01:00
Alice Ryhl 38151f30cb readme: unlist 1.32.x as LTS release (#6997) 2024-11-29 13:16:35 +00:00
Alice Ryhl 5dda72d338 ci: pin valgrind to rustc 1.82 (#6998) 2024-11-29 21:50:01 +09:00
Nur c07257f99f io: simplify io readiness logic (#6966) 2024-11-21 17:31:39 +01:00
Taliyah Webb d08578fc9a time: fix a typo in Instant docs (#6982) 2024-11-20 12:02:55 +00:00
tiif 4047d7962a miri: add annotations for tests with miri ignore (#6981) 2024-11-20 11:44:28 +01:00
Maarten de Vries cbdceb91ac io: add AsyncFd::try_io() and try_io_mut() (#6967) 2024-11-19 17:55:54 +01:00
Hamir Mahal d4178cf349 tokio: avoid positional fmt params when possible (#6978) 2024-11-18 13:50:58 +01:00
tiif 2f899144ed io: avoid ptr->ref->ptr roundtrip in RegistrationSet (#6929) 2024-11-16 11:16:09 +01:00
tiif 6255598baa docs: update miri test command in CONTRIBUTING.md (#6976) 2024-11-15 17:29:11 +01:00
Jonas Fassbender 772e0ca8a6 docs: fix documentation build on Windows (#6945) 2024-11-14 01:28:55 +09:00
Michael_Liu 3b677d1fde net: fix docs discription in unix module (#6791) 2024-11-11 14:14:46 +00:00
Alice Ryhl bb7ca7507b chore: prepare Tokio v1.41.1 (#6959)
Signed-off-by: Alice Ryhl <[email protected]>
2024-11-07 11:56:09 +01:00
Russell Cohen 4a34b77af5 metrics: fix bug with wrong number of buckets for the histogram (#6957) 2024-11-07 08:45:36 +01:00
DaniPopes 8897885425 docs: fix mismatched backticks in CONTRIBUTING.md (#6951)
It's rendered correctly at least on GitHub, but syntax highlighting fails after that point.
2024-11-04 10:29:57 +00:00
Taiki Endo 0dbdd196b6 ci: update cargo-check-external-types to 0.1.13 (#6949) 2024-11-02 16:50:00 +09:00
Joseph Perez 94e55c092b net: fix typo in TcpStream internal comment (#6944) 2024-10-29 09:31:39 +00:00
Jonas Fassbender 4468f27c31 metrics: fixed flaky worker_steal_count test (#6932) 2024-10-28 09:26:45 +01:00
Jonas Fassbender 070a825999 metrics: removed race condition from global_queue_depth_multi_thread test (#6936) 2024-10-27 19:36:18 +01:00
Jonas Fassbender 946401c345 net: display net requirement for net::UdpSocket in docs (#6938) 2024-10-26 12:37:39 +02:00
Taiki Endo 0c01fd23b4 ci: use patched version of cargo-check-external-types to fix CI failure (#6937) 2024-10-26 10:27:59 +02:00
Alice Ryhl ebe241647e ci: use cargo deny (#6931) 2024-10-23 18:48:07 +02:00
Motoyuki Kimura 01e04daaa1 chore: prepare Tokio v1.41.0 (#6917) 2024-10-22 11:22:33 +02:00
Josh McKinney 92ccadeb3c runtime: fix stability feature flags for docs (#6909) 2024-10-22 11:19:57 +02:00
Russell Cohen fbfeb9a68a metrics: rename *_poll_count_* to *_poll_time_* (#6924)
A consistent bit of feedback I've heard is that the `poll_count_histogram` name is a little confusing since the value customers actually get out of it is `poll_times`.

This renames all public APIs from `poll_count` to `poll_time`. The existing APIs were deprecated with one exception: the newly added `poll_count_histogram_configuration` which hasn't been released yet was simply renamed.
2024-10-22 09:21:07 +02:00
Russell Cohen da745ff335 metrics: add H2 Histogram option to improve histogram granularity (#6897) 2024-10-21 14:05:45 +02:00
Jonas Fassbender ce1c74f1cc metrics: fix deadlock in injection_queue_depth_multi_thread test (#6916) 2024-10-21 10:04:39 +02:00
Motoyuki Kimura 28c9a14a2e metrics: rename injection_queue_depth to global_queue_depth (#6918) 2024-10-18 19:34:06 +00:00
Alice Ryhl 32e0b4325f ci: freeze FreeBSD and wasm-unknown-unknown on rustc 1.81 (#6911)
Signed-off-by: Alice Ryhl <[email protected]>
2024-10-18 13:14:17 +02:00
Rafael BachmannandRafael Bachmann 1656d8e231 sync: add mpsc::Receiver::blocking_recv_many (#6867)
Fixes: #6865
Co-authored-by: Rafael Bachmann <[email protected]>
2024-10-17 11:02:12 +02:00
Russell Cohen c9e998e4b3 ci: print the correct sort order of the dictionary on failure (#6905) 2024-10-17 10:45:38 +02:00
Noah Kennedy 512e9decfb rt: add LocalRuntime (#6808)
This change adds LocalRuntime, a new unstable runtime type which cannot be transferred across thread boundaries and supports spawn_local when called from the thread which owns the runtime.

The initial set of docs for this are iffy. Documentation is absent right now at the module level, with the docs for the LocalRuntime struct itself being somewhat duplicative of those for the `Runtime` type. This can be addressed later as stabilization nears.

This API has a few interesting implementation details:
- because it was considered beneficial to reuse the same Handle as the normal runtime, it is possible to call spawn_local from a runtime context while on a different thread from the one which drives the runtime and owns it. This forces us to check the thread ID before attempting a local spawn.
- An empty LocalOptions struct is passed into the build_local method in order to build the runtime. This will eventually have stuff in it like hooks.

Relates to #6739.
2024-10-12 10:39:23 -05:00
Motoyuki Kimura 5ada5114df task: stabilize task::Id related apis (#6891) 2024-10-11 10:38:07 +00:00
tiif 161b8c80d5 ci: test more things with miri (#6885) 2024-10-11 09:44:50 +02:00
Sören Meier 9cc4a81678 sync: add watch::Sender::sender_count (#6836)
This makes it possible to check if other senders exist. For example
If you are using a Sender as a subscriber to get a Receiver and might want
to know if the real sender is still running.
2024-10-11 04:31:11 +02:00
Name 679d7657dc io: document cancel safety of AsyncFd methods (#6890) 2024-10-09 01:08:41 +09:00
Hayden Stainsby c3a935541d task: add task size to tracing instrumentation (#6881)
In Tokio, the futures for tasks are stored on the stack unless they are
explicitly boxed, either by the user or auto-boxed by Tokio when they
are especially large. Auto-boxing now also occurs in release mode
(since #6826).

Having very large futures can be problematic as it can cause a stack
overflow. In some cases it might be desireable to have smaller futures,
even if they are placed on the heap.

This change adds the size of the future driving an async task or the
function driving a blocking task to the tracing instrumentation. In the
case of a future that is auto-boxed by Tokio, both the final size as well
the original size before boxing is included.

To do this, a new struct `SpawnMeta` gets passed down from where a
future might get boxed to where the instrumentation is added. This
contains the task name (optionally) and the original future or function
size. If the `tokio_unstable` cfg flag and the `tracing` feature aren't both
enabled, then this struct will be zero sized, which is a small improvement
on the previous behavior of unconditionally passing down an `Option<&str>`
for the name.

This will make this information immediately available in Tokio Console,
and will enable new lints which will warn users if they have large futures
(just for async tasks).

We have some tests under the `tracing-instrumentation` crate which test
that the `size.bytes` and `original_size.bytes` fields are set correctly.

The minimal version of `tracing` required for Tokio has been bumped from
0.1.25 to 0.1.29 to get the `Value` impl on `Option<T>`. Given that the current
version is 0.1.40, this seems reasonable, especially given that Tracing's MSRV
is still lower than Tokio's in the latest version.
2024-10-08 10:51:03 +02:00
Nur 29cd6ec1ec time: import Future trait from std instead of futures_core (#6884) 2024-10-07 14:13:09 +02:00
Evan RittenhouseandAlice Ryhl b68f5c7f38 task: stabilize task ids (#6793)
Co-authored-by: Alice Ryhl <[email protected]>
2024-10-06 08:50:21 +00:00
Motoyuki Kimura 6c5dbfa08c readme: update miri test command (#6883) 2024-10-05 17:22:20 +02:00
oxalica 2c14f88c90 macros: suppress clippy::needless_return in #[tokio::main] (#6874) 2024-09-28 12:33:51 +02:00
shray sharma e2e1e8e71d sync: fix Stream link in broadcast docs (#6873) 2024-09-27 13:49:06 +02:00
Timo 21df16d759 sync: apply cooperative scheduling to sync::broadcast::Receiver (#6870) 2024-09-26 16:52:46 +02:00
Timo c8af499990 sync: apply cooperative scheduling to sync::watch (#6846) 2024-09-26 12:36:22 +00:00
Nick Mathewson 623928e371 net: add conversions for unix SocketAddr (#6868) 2024-09-25 13:56:52 +00:00
Motoyuki Kimura 09bc9a05e4 chore: use boxed slice if possible (#6858) 2024-09-25 19:45:28 +09:00
Alice Ryhl 82628b8a78 metrics: don't hang in injection_queue_depth_multi_thread test (#6862) 2024-09-24 08:34:17 +02:00
Alice Ryhl 21cf5a5469 runtime: avoid pointer casts in IO driver on miri (#6859)
Signed-off-by: Alice Ryhl <[email protected]>
2024-09-23 20:32:37 +02:00
vxzyfx's github 8ef5163df8 stream: fix link on Peekable (#6861) 2024-09-23 14:56:42 +00:00
Owen Leung 542197cdb9 metrics: stabilize injection_queue_depth metric (#6854) 2024-09-22 18:38:37 +02:00
vxzyfx's github a302367b8f net: change quotes in docs (#6852) 2024-09-21 13:53:34 +02:00
Maximilian Hils b5de84d19b runtime: box futures larger than 16k on release mode (#6826) 2024-09-16 22:15:44 +02:00
Jonas Fassbender 02aaea28b9 sync: document runtime compatibility (#6833) 2024-09-16 21:58:24 +02:00
Rustin 83e922f051 macros: render more comprehensible documentation for try_join! (#6841)
Signed-off-by: Rustin170506 <[email protected]>
2024-09-14 11:34:45 +02:00
Benjamin Richner a2496548d1 net: fix examples for TcpSocket::{set_nodelay,nodelay} (#6840) 2024-09-12 15:07:16 +02:00
Motoyuki Kimura 0cea36fa3d net: fix handling of leading zero byte in from_abstract_name (#6838) 2024-09-11 20:15:12 +02:00
Nam Se Hyun d6213594ca fs: make available to wasm under tokio_unstable (#6822) 2024-09-11 12:55:07 +00:00
Alice Ryhl 91169992b2 io: recommend OwnedFd with AsyncFd (#6821)
Signed-off-by: Alice Ryhl <[email protected]>
2024-09-06 09:52:08 +02:00
Rustin 8046a87a99 macros: render more comprehensible documentation for join! (#6814)
Signed-off-by: Rustin170506 <[email protected]>
2024-09-06 09:36:25 +02:00
Sylwester Rąpała 5dcc848fc8 sync: add #[must_use] to Notified (#6828) 2024-09-06 09:03:27 +02:00
Timo bd4ccae184 time: add abstraction for RwLock to remove poisoning aspect (#6807)
With #6779 we removed unnecessary allocations from the timerwheel by
wrapping it in an `std::sync::RwLock`. Since the `Mutex` used in this
part of the project uses an abstraction in `loom::sync::Mutex` to get
rid of the poisoning aspects of `std::sync::Mutex` the same should
probably be done for the used read-write lock struct.

This commit introduces an abstraction to get rid of the poisoning
aspects of `std::sync::RwLock` by introducing a wrapper to the
`loom::sync` module similar to `loom::sync::Mutex`.

Refs: #6779
2024-09-05 23:48:05 +09:00
Dirkjan Ochtman 4ed0fa21e4 chore: prepare tokio-stream v0.1.16 (#6825) 2024-09-05 12:42:22 +02:00
Eduardo Sánchez Muñoz 12b2567b95 chore: use poll_fn from std (#6810) 2024-09-05 09:54:06 +02:00
Timo 35f244ad09 chore: prepare tokio-util v0.7.12 (#6823) 2024-09-05 00:22:11 +02:00
Sarek Høverstad Skotåm 1166ecc2ac config: enable full for tokio-util in the playground (#6818) 2024-09-03 20:34:20 +00:00
Antonio de la Vega 27539ae3bd runtime: fix race in yield_defers_until_park test (#6809) 2024-08-31 21:34:22 +02:00
Motoyuki Kimura ea6d652a10 chore: prepare Tokio v1.40.0 (#6806) 2024-08-30 10:03:16 +02:00
Havish Maka 11f66f43a0 chore: replace ready! with std::task::ready! (#6804) 2024-08-29 22:02:56 +02:00
Timo 479a56a010 time: eliminate timer wheel allocations (#6779) 2024-08-27 22:18:29 +02:00
Noah Kennedy b37f0de28a runtime: implement initial set of task hooks (#6742) 2024-08-27 15:27:58 +02:00
Yotam Ofek c9fad08466 codec: fix typo in the docs for Encoder::Error (#6800) 2024-08-27 09:08:22 +02:00
Havish Maka cc70a211ad task: add join_all method to JoinSet (#6784)
Adds join_all method to JoinSet. join_all consumes JoinSet and awaits
the completion of all tasks on it, returning the results of the tasks in
a vec. An error or panic in the task will cause join_all to panic,
canceling all other tasks.

Fixes: #6664
2024-08-27 01:06:52 +09:00
Rafael Bachmann 1ac8dff213 task: add AbortOnDropHandle type (#6786) 2024-08-20 10:58:04 +02:00
Daniel Sedlak ff3f2a8878 io: add SimplexStream (#6589) 2024-08-19 15:47:57 +02:00
rosscanning 5b9a290acd io: clarify zero remaining capacity case (#6790) 2024-08-19 09:09:24 +09:00
dpl 70569bd009 task: fix typo in TaskTracker docs (#6792) 2024-08-18 15:09:19 +02:00
Tobias Bucher 9bd6702a3f sync: mark mpsc types as UnwindSafe (#6783) 2024-08-18 13:36:51 +02:00
mox692 365269adaf Merge 'tokio-1.39.x' into master (#6788) 2024-08-17 19:35:28 +09:00
Motoyuki Kimura 3d439ab711 chore: prepare Tokio v1.39.3 (#6782) 2024-08-17 10:26:43 +02:00
Motoyuki Kimura b2ea40bb54 net: add handling for abstract socket name (#6772) 2024-08-16 23:50:34 +09:00
Rafael Bachmann 5ea3c63d7e sync: document mpsc channel allocation behavior (#6773) 2024-08-16 12:31:03 +02:00
Eliza Weisman 56f3f40c15 tests: handle ECONNREFUSED in uds_stream::epollhup (#6778)
## Motivation

Currently, the test `uds_stream::epollhup` expects that a
`UdsStream::connect` future to a Unix socket which is closed by the
accept side to always fail with `io::ErrorKind::ConnectionReset`. On
illumos, and potentially other systems, it instead fails with
`io::ErrorKind::ConnectionRefused`.

This was discovered whilst adding an illumos CI job in PR #6769. See:
https://github.com/tokio-rs/tokio/pull/6769#issuecomment-2284753794

## Solution

This commit changes the test to accept either `ConenctionReset` or
`ConnectionRefused`. This way, we are more tolerant of different
operating systems which may decide to return slightly different errnos
here. Both ECONNREFUSED and ECONNRESET seem reasonable to expect in this
situation, although arguably, ECONNREFUSED is actually more correct: the
acceptor did not accept the connection at all, which seems like
"refusing" it to me...
2024-08-16 10:55:32 +02:00
Eliza Weisman 2d697fc92b tests: handle spurious EWOULDBLOCK in io_async_fd (#6776)
* tests: handle spurious EWOULDBLOCK in io_async_fd

## Motivation

The `io_async_fd.rs` tests contain a `drain()` function, which
currently performs synchronous reads from a UDS socket until it returns
`io::ErrorKind::WouldBlock` (i.e., errno `EWOULDBLOCK`/`EAGAIN`). The
*intent* behind this function is to ensure that all data has been
drained from the UDS socket's buffer...which is what it appears to
do...on Linux. On other systems, it appears that an `EWOULDBLOCK` or
`EAGAIN` may be returned before enough data has been read from the UDS
socket to result in the other end being notified that the socket is now
writable. In particular, this appears to be the case on illumos, where
the tests using this function hang forever (see [this comment][1] on PR
#6769).

To my knowledge, this behavior is still POSIX-compliant --- the
reader will still be notified that the socket is readable, and if it
were actually doing non-blocking IO, it would continue reading upon
receipt of that notification. So, relying on `EWOULDBLOCK` to indicate
that the socket has been sufficiently drained appears to rely on
Linux/FreeBSD behavior that isn't necessarily portable to other Unices.

## Solution

This commit changes the `drain()` function to take an argument for the
number of bytes *written* to the socket previously, and continue looping
until it has read that many bytes, regardless of whether `EWOULDBLOCK`
is returned. This should ensure that the socket is drained on all
POSIX-compliant systems, and indeed, the `io_async_fd::reset_writable`
and `io_async_fd::poll_fns` tests no longer hang forever on illumos.

I think making this change is an appropriate solution to the
test failure here, as the `drain()` function is part of the test, rather
than the code in Tokio *being* tested, and (as I mentioned above) the
use of blocking reads on a non-blocking socket without a mechanism to
continue reading when the socket becomes readable again is not really
something a real life program seems likely to do. Ensuring that all the
written bytes have been read by passing in a byte count seems more
faithful to what the test is actually *trying* to do here, anyway.

Thanks to @jclulow for debugging what was going on here!

This change was cherry-picked from commit
f18d6ed7d4 from PR #6769, so that the fix
can be merged separately.

[1]: https://github.com/tokio-rs/tokio/pull/6769#issuecomment-2284753794

Signed-off-by: Eliza Weisman <[email protected]>
2024-08-15 15:44:36 +00:00
Rafael Bachmann 39c3c19bbd macros: improve documentation for select! (#6774) 2024-08-14 15:49:28 +02:00
Eliza Weisman 694577fa85 Add config file to enable Buildomat CI for illumos (#6768)
## Motivation

As described in #6763, Tokio compiles for the [illumos] operating
system, but we don't presently have automated tests on illumos. We would
like to add illumos CI jobs for Tokio using [Buildomat], a CI system
which supports illumos. Buildomat CI jobs for Tokio will run on
infrastructure contributed by Oxide Computer Company.

In order for Buildomat to watch for commits to the repo, we must first
add a configuration file in `.github/buildomat/config.toml` with the
`enable = true` key. This config file must be present on the repo's main
branch for Buildomat to enable builds for the repo. See [here] for
details.

## Solution

This branch adds a `.github/buildomat` directory containing a config
file and a README summarizing what the configs in that directory are
for, as well as documenting how to get help diagnosing illumos CI
failures.


This branch does *not* add scripts for actually running CI jobs on
Buildomat. Since the config file must be present on the repo's main
branch before Buildomat runs CI jobs for the repo, I'd like to merge the
config file separately from the actual build scripts. This way, I can
actually have the build jobs run on the PR that adds them, making it
easier to ensure everything is working correctly before merging.

Closes #6766, which is obsoleted by this branch.

[illumos]: https://www.illumos.org/
[Buildomat]: https://github.com/oxidecomputer/
[here]:
    https://github.com/oxidecomputer/buildomat/blob/main/README.md#per-repository-configuration
2024-08-12 16:22:21 +00:00
Vrtgs 17819062e2 tokio: update code according to new MSRV (#6764) 2024-08-11 11:55:22 +02:00
Sainath Singineedi 6ad1912353 task: add #[must_use] to JoinHandle::abort_handle (#6762) 2024-08-09 20:57:31 +00:00
Caleb Leinz (he/him) a491b16a89 sync: add {TrySendError,SendTimeoutError}::into_inner (#6755) 2024-08-08 00:06:37 +02:00
Austin Bonander 0ecf5f0f03 task: include panic msg when printing JoinError (#6753) 2024-08-07 16:54:02 +02:00
Adam Cigánek 1e798d26ed time: wake DelayQueue when removing last item (#6752) 2024-08-06 16:22:31 +02:00
Alice Ryhl ab53bf0c47 runtime: prevent niche-optimization to avoid triggering miri (#6744) 2024-08-03 12:32:50 +02:00
Motoyuki Kimura 338e13b04b task: use NonZeroU64 for task::Id (#6733) 2024-08-01 14:45:35 +00:00
Motoyuki Kimura 1077b0b29d io: use vectored io for write_all_buf when possible (#6724) 2024-07-29 19:39:44 +02:00
Hayden Stainsby 0cbf1a5ada time,sync: make Sleep and BatchSemaphore instrumentation explicit roots (#6727)
When instrumenting resources in Tokio, a span is created for each
resource. Previously, all resources inherited the currently active span
as their parent (tracing default). However, this would keep that parent
span alive until the resource (and its span) were dropped. This is often
not correct, as a resource may be created in a task and then sent
elsewhere, while the originating task ends.

This artificial extension of the parent span's lifetime would make it
look like that task was still alive (but idle) in any system reading the
tracing instrumentation in Tokio, for example Tokio Console as reported
in tokio-rs/console#345.

In #6107, most of the existing resource spans were updated to
make them explicit roots, so they have no contextual parent. However,
2. were missed:
- `Sleep`
- `BatchSemaphore`

This change alters the resource spans for those 2 resources to also make
them explicit roots.
2024-07-29 12:06:13 +02:00
Hayden Stainsby 04c2718508 docs: reiterate that [build] doesn't go in Cargo.toml (#6728)
To enable unstable features in Tokio, passing `--cfg tokio_unstable` to
the compiler is necessary. We document how to do this in a variety of
ways in the main Tokio (lib.rs) documentation.

One way is to add a `[build]` section to the file `.cargo/config.toml`.
Even though this filename is stated in the documentation, it is quite
common that first time users (including this author, some time ago) put
it in their `Cargo.toml` file instead.

This change adds a "warning" section to the documentation to reiterate
the point that this section doesn't go in the cargo manifest
(`Cargo.toml`).
2024-07-29 11:23:29 +02:00
Niklas Fiekas ebda4c3d3f process: stabilize Command::process_group (#6731) 2024-07-27 23:08:40 +02:00
Alice Ryhl f602eae499 chore: prepare Tokio v1.39.2 (#6730) 2024-07-27 12:36:48 +02:00
Alice Ryhl 438def7957 macros: allow temporary lifetime extension in select (#6722) 2024-07-26 17:36:28 +01:00
Motoyuki Kimura ee8d4d1b05 chore: fix ci failures (#6725) 2024-07-25 20:30:23 +02:00
Dirkjan Ochtman 3297052763 ci: test Quinn in CI (#6719) 2024-07-25 11:37:46 +02:00
Alice Ryhl f8fe0ffb23 chore: prepare Tokio v1.39.1 (#6716) 2024-07-23 18:28:04 +02:00
Alice Ryhl 47210a8e6e time: revert "avoid traversing entries in the time wheel twice" (#6715)
This reverts commit 8480a180e6.
2024-07-23 16:09:28 +00:00
Alice Ryhl 29545d9037 runtime: ignore many_oneshot_futures test for alt scheduler (#6712) 2024-07-23 16:35:20 +02:00
Alice Ryhl 48e35c11d9 chore: release Tokio v1.39.0 (#6711) 2024-07-23 15:30:11 +02:00
Alice Ryhl dd1d37167d macros: accept IntoFuture args for macros (#6710) 2024-07-23 12:52:25 +00:00
Alice Ryhl 6a1a7b1591 chore: prepare tokio-macros v2.4.0 (#6707) 2024-07-23 14:45:06 +02:00
Kenny Kerr 51b03f0334 deps: update to windows-sys v0.52 (#6154) 2024-07-23 14:43:23 +02:00
Thomas de Zeeuw 754a1fb03c deps: update to Mio v1 (#6635) 2024-07-23 14:26:07 +02:00
Sebastian Urban 90b23a9584 metrics: add worker thread id (#6695) 2024-07-23 12:41:33 +02:00
Sebastian Urban b69f16aa21 metrics: add worker_park_unpark_count (#6696) 2024-07-23 09:15:54 +02:00
Alex Butler 6e845b794d time: support IntoFuture with timeout (#6666) 2024-07-22 23:29:18 +02:00
Tim Vilgot Mikael Fredenberg feb742c58e chore: replace num_cpus with available_parallelism (#6709) 2024-07-22 23:15:23 +02:00
Alice Ryhl 15cd5146d4 chore: increase MSRV to 1.70 (#6645) 2024-07-22 18:01:27 +00:00
Alice Ryhl 56f4bc6543 chore: make 1.38 an LTS (#6706) 2024-07-21 18:28:12 +02:00
Motoyuki Kimura 3ad5b6df1a runtime: add cfg for loom specific code (#6694) 2024-07-21 17:26:36 +02:00
Russell Cohen 1be8a8e691 metrics: stabilize num_alive_tasks (#6619) 2024-07-18 22:08:29 +02:00
Motoyuki Kimura da17c61464 task: add size check for user-supplied future (#6692) 2024-07-18 11:54:37 +00:00
Ikko Eltociear Ashimine f71bded943 sync: fix typo in name of test (#6693) 2024-07-18 11:05:16 +02:00
Motoyuki Kimura fc058b9561 io: update tokio::io::stdout documentation (#6674) 2024-07-16 19:34:09 +02:00
wathenjiang c0280624f3 Merge 'tokio-1.38.1' into 'master' (#6689) 2024-07-17 00:02:27 +08:00
Evan Rittenhouse 1e286689ff runtime: fix yield_calls_park_before_scheduling_again test (#6679) 2024-07-16 17:29:19 +02:00
Weijia Jiang 14b9f71157 chore: release Tokio v1.38.1 (#6688) 2024-07-16 17:16:29 +02:00
Weijia Jiang 24344dfe4b time: fix race condition leading to lost timers (#6683) 2024-07-16 13:25:59 +00:00
Paolo Barbolini 15925efe43 macros: fix doc format issue (#6686) 2024-07-16 12:13:41 +02:00
Matthew Leach 4825c444eb test: fix tests when '-' is absent from kernel version (#6681)
On my machine, any test that calls `is_pidfd_available` fails as my
kernel string does not contain a '-'; the code expects there to be one.

Fix the test so that is works regardless on whether the kernel string
contains a '-'.
2024-07-14 13:38:23 +09:00
sharpened-nacho c8f3539bc1 stream: make stream adapters public (#6658) 2024-07-02 20:49:34 +00:00
Alice Ryhl b2e4c5fc9e io: hardcode platform list in short-read optimization (#6668) 2024-07-02 20:25:49 +00:00
teor 4d0d89fb70 task: document behavior of JoinSet::try_join_next when all tasks are running (#6671) 2024-07-02 17:54:59 +02:00
二手掉包工程师 fe7285d3d1 sync: add {Receiver,UnboundedReceiver}::{sender_strong_count,sender_weak_count} (#6661) 2024-07-02 23:41:15 +08:00
Michael MaciasandWeijia Jiang dff4ecd0e7 io: implement AsyncSeek for Empty (#6663)
* io: implement `AsyncSeek` for `Empty`

* io: add more tests for seeking `Empty`

This adds more tests seeking with other kinds of `SeekFrom`. It follows
the same structure as used in
rust-lang/rust@f1cd17961c.

See <https://github.com/tokio-rs/tokio/pull/6663#discussion_r1659491016>.

* io: add inline attribute to `AsyncSeek` implementations

This follows the style of the other trait implementations of `Empty`.

See <https://github.com/tokio-rs/tokio/pull/6663#discussion_r1658835942>.

---------

Co-authored-by: Weijia Jiang <[email protected]>
2024-07-01 09:50:49 +08:00
Alice Ryhl 68d0e3cb5f metrics: rename num_active_tasks to num_alive_tasks (#6667) 2024-06-30 15:02:29 +02:00
Tobias Nießen 65d0e08d39 runtime: fix typo in unhandled_panic (#6660) 2024-06-28 01:10:14 +09:00
Hai-Hsin 06582776a5 codec: fix length_delimited docs examples (#6638) 2024-06-23 13:52:51 +09:00
Eric Seppanen ed4ddf443d io: fix trait bounds on impl Sink for StreamReader (#6647)
This impl had a bound on `StreamReader<S, E>`; this is incorrect
because:
- The second generic parameter to `StreamReader` is not an error type;
  it's a buffer type.
- The `Stream` error type in `StreamReader` should not need to be the
  same as the `Sink` error type.

This "passthrough" `Sink` impl was effectively unusable because it
required the `Sink` error type be the same as the `StreamReader` buffer
type.

Resolve this by allowing the `StreamReader` buffer to be anything in
this impl.
2024-06-21 15:00:33 +02:00
Alice Ryhl 9a75d6f7f7 metrics: use MetricAtomic* for task counters (#6624) 2024-06-17 08:33:08 +00:00
Uwe Klotz 3bf4f93854 sync: add watch::Sender::same_channel (#6637) 2024-06-15 21:11:35 +02:00
FabijanC 39cf6bba00 macros: typo fix in join.rs and try_join.rs (#6641) 2024-06-15 21:10:47 +02:00
Weijia Jiang 8480a180e6 time: avoid traversing entries in the time wheel twice (#6584) 2024-06-14 11:03:47 +02:00
Timo 53ea44bfb9 sync: add CancellationToken::run_until_cancelled (#6618) 2024-06-13 10:58:45 +02:00
Weijia Jiang a865ca139a rt: relaxed trait bounds for LinkedList::into_guarded (#6630) 2024-06-13 08:50:28 +02:00
Niki C 479f736935 io: improve panic message of ReadBuf::put_slice() (#6629) 2024-06-13 01:09:59 +09:00
Marek Kuskowski 17555d71d9 sync: implement Default for watch::Sender (#6626) 2024-06-10 10:44:45 +02:00
Conrad Ludgate 341b5daa6e metrics: add spawned_tasks_count, rename active_tasks_count (#6114) 2024-06-09 12:25:54 +02:00
Rob Ede 53b586c5b9 task: stabilize consume_budget (#6622) 2024-06-08 22:17:06 +02:00
Hai-Hsin 833ee027d0 macros: allow unhandled_panic behavior for #[tokio::main] and #[tokio::test] (#6593) 2024-06-07 20:48:56 +09:00
Aaron Schweiger 126ce89bb4 task: implement Clone for AbortHandle (#6621) 2024-06-07 09:17:25 +02:00
Russell Cohen 8e15c234c6 metrics: add MetricAtomicUsize for usized-metrics (#6598) 2024-06-06 10:08:46 +02:00
John-John Tedro 16fccafb41 docs: fix docsrs builds with the fs feature enabled (#6585) 2024-06-05 08:20:27 +00:00
Armillus 3f397ccded io: read during write in copy_bidirectional and copy (#6532) 2024-06-05 00:29:28 +02:00
Emil Loer 49609d073f test: make Spawn forward size_hint (#6607) 2024-06-04 23:42:42 +02:00
Alan Somers a91d43823c ci: update FreeBSD CI environment (#6616)
Use the newly released FreeBSD 14.1.
2024-06-04 23:37:13 +02:00
Timo 8fca6f6dad process: add Command::as_std_mut (#6608) 2024-06-04 13:34:22 +02:00
Weijia Jiang 75c953bd63 time: fix big time panic issue (#6612) 2024-06-04 09:45:35 +02:00
Alice Ryhl 14c17fc096 chore: prepare Tokio v1.38.0 (#6601) 2024-05-30 13:24:58 -07:00
Alice Ryhl 65cbf730de chore: prepare tokio-macros v2.3.0 (#6600) 2024-05-30 13:21:51 -07:00
Alice Ryhl dbf93c7184 sync: fix incorrect is_empty on mpsc block boundaries (#6603) 2024-05-30 13:21:16 -07:00
Weijia Jiang 873cb8ae2f runtime: move task out of the lifo_slot in block_in_place (#6596) 2024-05-30 10:45:45 +02:00
SteveLauC 97bb47b480 task: fix a typo in doc of LocalSet::run_until (#6599) 2024-05-30 10:44:53 +02:00
Russell Cohen 86658bd87d metrics: stabilize RuntimeMetrics::worker_count (#6556) 2024-05-28 21:55:20 +02:00
Pau Freixes 9e00b266e0 sync: add Notify::notify_last (#6520) 2024-05-27 11:18:34 +00:00
Maxwell Borden 6c42d286b3 net: fix misleading NamedPipeServer example (#6590)
The previous NamedPipeServer doc example seemed to imply that the return
type of `NamedPipeServer::connect()` was a
`Future<Result<some_kind_of_client>>>`, however, `connect()` returns a
`Future<Result<()>>>`. The following line of code reopening the pipe
would shadow the newly connected pipe immediately, making the following
spawned task pointless. Hopefully these changes make it more clear what
should be happening in the example.
2024-05-26 12:25:19 +02:00
Josh McKinney 3a6fdc0568 license: fix formatting and remove year in licenses (#6451) 2024-05-26 09:29:27 +00:00
Conrad Ludgate 2890d0c3db metrics: fix blocking_threads count (#6551) 2024-05-25 21:49:17 +00:00
Maxwell Borden 0a85a9662d net: implement Clone for NamedPipeInfo (#6586) 2024-05-25 22:14:59 +02:00
Alan SomersandFrederick Mayle 12920cea45 tests: update nix and mio-aio dependencies (#6552)
nix 0.29.0 and mio-aio 0.9.0 use I/O Safety.

Co-authored-by: Frederick Mayle <[email protected]>
2024-05-25 17:30:36 +02:00
Russell Cohen cba86cf1b1 metrics: add MetricAtomicU64 and use in metrics (#6574) 2024-05-23 18:41:01 +02:00
Roy Wellington 16ef7b1fd5 docs: fix stdin documentation (#6581)
The code for `output` indicates that only sets `stdout` and `stderr`, 
yet the docs for `stdin` indicated that it too would be set. This seems 
like it was just a simple copy/paste typo, so correct `stdin` to note
that it just defaults to `inherit`.

Fixes #6577.
2024-05-23 13:52:57 +09:00
Weijia Jiang 1914e1e4b9 time: use sharding for timer implementation (#6534) 2024-05-22 11:54:26 +00:00
二手掉包工程师 e62c3e9269 task: add tokio::task::join_set::Builder::spawn_blocking (#6578)
Signed-off-by: hi-rustin <[email protected]>
2024-05-22 13:35:12 +02:00
M.Amin Rayej 0b651c070f fs: add File::create_new (#6573) 2024-05-22 13:24:48 +02:00
Alice Ryhl a02407171a task: clarify that you can't abort spawn_blocking tasks (#6571) 2024-05-19 16:09:22 +00:00
Michael Scholten daa89017da ci: fix new clippy warnings (#6569) 2024-05-18 10:09:37 +02:00
Alice Ryhl 35c6fd9924 ci: set RUSTUP_WINDOWS_PATH_ADD_BIN=1 (#6568) 2024-05-17 13:03:22 +02:00
Russell Cohen d221c500fa docs: gate taskdump compiler_error behind not(doc) (#6564) 2024-05-16 12:14:07 +02:00
John-John Tedro ced7739f69 tokio: use ptr::addr_of instead of pointer arithmetic in linked_list (#6561) 2024-05-16 10:30:48 +02:00
William Wen 18e048d764 sync: always drop message in destructor for oneshot receiver (#6558) 2024-05-15 13:57:35 +02:00
Weijia Jiang df77063485 time: remove the true_when field in TimerShared (#6563) 2024-05-15 09:32:39 +02:00
Alice Ryhl d085260ee0 metrics: fix flaky injection_queue_depth test (#6559) 2024-05-14 21:01:49 +00:00
Sebastian SchildtandAkhil Thankachan Thomas 227979f091 net: support QNX OS (#6421)
Co-authored-by: Akhil Thankachan Thomas <[email protected]>
2024-05-14 13:11:37 +02:00
Kezhu Wang 6fcd9c0217 macros: make #[tokio::test] append #[test] at the end of the attribute list (#6497) 2024-05-05 16:28:59 +00:00
Alice Ryhl 2a0df5fb05 ci: bump nightly to nightly-2024-05-05 (#6538) 2024-05-05 15:43:11 +00:00
Alice Ryhl b652a4e64c util: no default features for hashbrown (#6541) 2024-05-05 17:18:49 +02:00
Alice Ryhl 7f59a6ea85 tests: remove tests module from integration tests (#6540) 2024-05-05 17:18:37 +02:00
Alice Ryhl 75e5b3d96d runtime: ignore yield_calls_park_before_scheduling_again test (#6537) 2024-05-05 11:06:56 +02:00
Alice Ryhl cdf9d997dc chore: prepare tokio-util v0.7.11 (#6535) 2024-05-04 22:32:31 +02:00
Weijia Jiang f6eb1ee196 time: lazily init timers on first poll (#6512) 2024-05-03 15:37:52 +02:00
Matthijs Brobbel b7d4fba707 sync: add mpsc::Receiver::{capacity,max_capacity} (#6511) 2024-05-03 13:44:01 +02:00
Motoyuki Kimura 3c8d8e60ca chore: fix latest rust-1.78.0 warnings (#6528) 2024-05-03 11:23:25 +02:00
Paolo Barbolini e971a5e7d7 util: use FIFO ordering in WakeList (#6521) 2024-05-01 14:19:23 +00:00
Paolo Barbolini 28439e2269 time: clean up implementation (#6517) 2024-05-01 14:50:40 +02:00
João Oliveira d33fdd86a3 time: check for overflow in Interval::poll_tick (#6487) 2024-04-25 09:02:11 +02:00
Valentin 731dde21dc runtime: clarify misleading use of UnsafeCell::with_mut (#6513)
The code that we're removing calls UnsafeCell::with_mut with the
argument `std::mem::drop`. This is misleading because the use of `drop`
has no effect. `with_mut` takes an argument of type
`impl FnOnce(*mut T) -> R`. The argument to the argument function is a
pointer. Dropping a pointer has no effect.

The comment above the first instance of this pattern claims that this
releases some resource. This is false because the call has no effect.
The intention might have been to drop the value behind the pointer. If
this did happen, it would be a bug because the resource (`waker`) would
be dropped again at the end of the function when the containing object
is dropped.

I looked through the history of this code. This code originally called
`with_mut` with the argument `|_| ()`. Calling `with_mut` with an
argument function that does nothing has a side effect when testing with
loom. When testing with loom, the code uses loom's UnsafeCell type
instead of std's. The intention of the code was likely to make use of
that side effect because we expect to have exclusive access here as we
are going to drop the containing object. The side effect is that loom
checks that Rust's reference uniqueness properties are upheld.

To continue to check this, I have only removed the use of `drop` while
keeping `with_mut`. It would be even better to have loom check this
implicitly when UnsafeCell is dropped. I created an issue about this in
loom [1].

Links: https://github.com/tokio-rs/loom/issues/349 [1]
2024-04-25 09:01:15 +02:00
LongYinan 9ed595767d wasm: support rt-multi-thread with wasm32-wasi-preview1-threads (#6510) 2024-04-24 09:45:54 +02:00
avtrujillo a73d6bf33a macros: #[cfg(not(test))] is no longer necessary for main macros (#6508) 2024-04-23 14:05:14 +02:00
Alex Yusiuk 8093712604 io: add copy_bidirectional_with_sizes (#6500) 2024-04-22 11:03:33 +02:00
Jainil Patel 19618905de time: fix test-util requirement for pause and resume in docs (#6503) 2024-04-21 14:12:36 +02:00
Motoyuki Kimura 2438b43671 sync: instrument Semaphore for task dumps (#6499) 2024-04-20 12:35:11 +02:00
Kevin Reid 125a185749 io: fix obsolete reference in ReadHalf::unsplit() documentation (#6498) 2024-04-20 14:21:31 +09:00
Kenny f3bfed30eb metrics: document Runtime::metrics (#6496) 2024-04-19 10:07:55 +02:00
Alice Ryhl 5ba12a7145 sync: document that Barrier::wait is not cancel safe (#6494)
Signed-off-by: Alice Ryhl <[email protected]>
2024-04-18 17:21:34 +02:00
Alice Ryhl 9c6ff3b7e5 sync: explain relation between watch::Sender::{subscribe,closed} (#6490)
Signed-off-by: Alice Ryhl <[email protected]>
2024-04-17 16:16:14 +02:00
Alice Ryhl 1f6fc55917 net: add missing types to module docs (#6482)
Signed-off-by: Alice Ryhl <[email protected]>
2024-04-13 17:22:11 +02:00
Josh McKinney a5bd0deaa5 docs: add --locked to cargo install commands (#6479) 2024-04-13 11:44:33 +02:00
Motoyuki Kimura ee68c1a8c2 sync: add examples for SemaphorePermit, OwnedSemaphorePermit (#6477) 2024-04-12 13:14:08 +02:00
Alice Ryhl 90e20bcad3 sync: use usize instead of u32 for SemaphorePermit::split (#6478)
Signed-off-by: Alice Ryhl <[email protected]>
2024-04-11 17:21:55 +00:00
Alice Ryhl bdf4c142c9 fs: rewrite file system docs (#6467) 2024-04-11 10:33:51 +02:00
dtolnay 43de364cd9 readme: mention cargo-docs-rs in CONTRIBUTING.md (#6475) 2024-04-11 10:33:01 +02:00
vvvviiv 224fea4f3c sync: add split method to the semaphore permit (#6472) 2024-04-10 15:55:44 +02:00
Pierre Fenoll ccee1d4493 task: make LocalKey::get work with Clone types (#6433)
Signed-off-by: Pierre Fenoll <[email protected]>
2024-04-10 11:41:58 +02:00
Rafael Bachmann be9328da75 chore: fix clippy warnings (#6466) 2024-04-08 20:44:18 +09:00
Aoi Kurokawa b6d74ac4eb runtime: add links in docs for issues and crates (#6473) 2024-04-08 10:47:57 +02:00
Alice Ryhl 5712aaf995 metrics: ignore worker_steal_count test (#6471) 2024-04-07 16:30:33 +02:00
dtolnay 431b7c5263 macros: render more comprehensible documentation for select! (#6468) 2024-04-06 22:57:29 +00:00
Quentin Perez 01ed7b55f7 net: add Apple visionOS support (#6465) 2024-04-06 18:09:43 +02:00
Taiki Endo 035a968bdd chore: fix typo (#6464) 2024-04-06 00:43:13 +09:00
Aoi Kurokawa a1acfd8c20 readme: add readme for tokio-stream (#6456) 2024-04-03 15:36:08 +09:00
Motoyuki Kimura 328a02c1ce runtime: improvements for global_queue_interval (#6445) 2024-04-03 14:10:13 +09:00
Bharath Vedartham e9ae5d4ce9 io: implement AsyncBufRead for Join (#6449)
Fixes: #6446
2024-04-02 13:00:44 +02:00
Jens Reidel d298049299 codec: make tracing feature optional for codecs (#6434)
Signed-off-by: Jens Reidel <[email protected]>
2024-03-30 18:20:05 +01:00
Timo 1fcb77db34 io: add T: ?Sized to tokio_util::io::poll_read_buf (#6441) 2024-03-30 12:13:06 +00:00
Siech0 3936ebdfe4 chore: update CI to clippy 1.77 (#6443) 2024-03-30 15:49:42 +09:00
433 changed files with 11401 additions and 4664 deletions
+2 -2
View File
@@ -1,10 +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_family: freebsd-14-0
image_family: freebsd-14-1
env:
RUST_STABLE: stable
RUST_NIGHTLY: nightly-2023-10-21
RUST_NIGHTLY: nightly-2024-05-05
RUSTFLAGS: -D warnings
# Test FreeBSD in a full VM on cirrus-ci.com. Test the i686 target too, in the
+20
View File
@@ -0,0 +1,20 @@
# Buildomat illumos CI
This directory contains CI configurations for the [illumos] operating system.
Tokio's illumos CI jobs are run using [Buildomat], a CI system developed by
Oxide Computer, which supports illumos. See [the Buildomat README] for more
details.
## illumos-Specific CI Failures
If your pull request's CI build fails on illumos, and you aren't able to easily
reproduce the failure on other operating systems, don't worry! The
[tokio-rs/illumos] team is responsible for maintaining Tokio's illumos support,
and can be called on to assist contributors with illumos-specific issues. Please
feel free to tag @tokio-rs/illumos to ask for help resolving build failures on
illumos
[illumos]: https://www.illumos.org/
[Buildomat]: https://github.com/oxidecomputer/buildomat
[the Buildomat README]: https://github.com/oxidecomputer/buildomat
[tokio-rs/illumos]: https://github.com/orgs/tokio-rs/teams/illumos
+8
View File
@@ -0,0 +1,8 @@
# Repository-level Buildomat configuration.
# See: https://github.com/oxidecomputer/buildomat#per-repository-configuration
# Enable buildomat. This one should be self-explanatory.
enable = true
# Allow CI runs for PRs from users outside the `tokio-rs` organization. Our
# buildomat jobs don't touch any secrets/keys, so this should be fine.
org_only = false
+6 -12
View File
@@ -13,18 +13,12 @@ permissions:
contents: read
jobs:
security-audit:
cargo-deny:
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
checks: write
contents: read
issues: write
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v4
- name: Audit Check
# https://github.com/rustsec/audit-check/issues/2
uses: rustsec/audit-check@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
+138 -63
View File
@@ -13,10 +13,13 @@ concurrency:
env:
RUSTFLAGS: -Dwarnings
RUST_BACKTRACE: 1
RUSTUP_WINDOWS_PATH_ADD_BIN: 1
# Change to specific Rust release to pin
rust_stable: stable
rust_nightly: nightly-2023-10-21
rust_clippy: '1.76'
rust_nightly: nightly-2024-05-05
# Pin a specific miri version
rust_miri_nightly: nightly-2024-10-21
rust_clippy: '1.77'
# When updating this, also update:
# - README.md
# - tokio/README.md
@@ -25,7 +28,7 @@ env:
# - tokio-util/Cargo.toml
# - tokio-test/Cargo.toml
# - tokio-stream/Cargo.toml
rust_min: '1.63'
rust_min: '1.70'
defaults:
run:
@@ -44,7 +47,6 @@ jobs:
- test-workspace-all-features
- test-integration-tests-per-feature
- test-parking_lot
- test-tracing-instrumentation
- valgrind
- test-unstable
- miri
@@ -64,10 +66,11 @@ jobs:
- loom-compile
- check-readme
- test-hyper
- test-quinn
- x86_64-fortanix-unknown-sgx
- check-redox
- wasm32-unknown-unknown
- wasm32-wasi
- wasm32-wasip1
- check-external-types
- check-fuzzing
- check-unstable-mt-counters
@@ -176,7 +179,7 @@ jobs:
run: |
set -euxo pipefail
RUSTFLAGS="$RUSTFLAGS -C panic=abort -Zpanic-abort-tests" cargo nextest run --workspace --exclude tokio-macros --exclude tests-build --all-features --tests
test-integration-tests-per-feature:
needs: basics
name: Run integration tests for each feature
@@ -242,34 +245,6 @@ jobs:
- name: Check tests with all features enabled
run: cargo check --workspace --all-features --tests
test-tracing-instrumentation:
# These tests use the as-yet unpublished `tracing-mock` crate to test the
# tracing instrumentation present in Tokio. As such they are placed in
# their own test crate outside of the workspace.
needs: basics
name: test tokio instrumentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_stable }}
- name: Install cargo-nextest
uses: taiki-e/install-action@v2
with:
tool: cargo-nextest
- uses: Swatinem/rust-cache@v2
- name: test tracing-instrumentation
run: |
set -euxo pipefail
cargo nextest run
working-directory: tokio/tests/tracing-instrumentation
env:
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
valgrind:
name: valgrind
needs: basics
@@ -279,7 +254,7 @@ jobs:
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_stable }}
toolchain: 1.82
- name: Install Valgrind
uses: taiki-e/install-action@valgrind
@@ -411,17 +386,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
- name: Install Rust ${{ env.rust_miri_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_nightly }}
toolchain: ${{ env.rust_miri_nightly }}
components: miri
- name: Install cargo-nextest
uses: taiki-e/install-action@v2
with:
tool: cargo-nextest
- uses: Swatinem/rust-cache@v2
- name: miri
# 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
cargo miri nextest run --features full --lib --tests --no-fail-fast
working-directory: tokio
env:
MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields
@@ -762,7 +739,15 @@ jobs:
docs:
name: docs
runs-on: ubuntu-latest
runs-on: ${{ matrix.run.os }}
strategy:
matrix:
run:
- os: windows-latest
- os: ubuntu-latest
RUSTFLAGS: --cfg tokio_taskdump
RUSTDOCFLAGS: --cfg tokio_taskdump
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
@@ -774,8 +759,8 @@ jobs:
run: |
cargo doc --lib --no-deps --all-features --document-private-items
env:
RUSTFLAGS: --cfg docsrs --cfg tokio_unstable --cfg tokio_taskdump
RUSTDOCFLAGS: --cfg docsrs --cfg tokio_unstable --cfg tokio_taskdump -Dwarnings
RUSTFLAGS: --cfg docsrs --cfg tokio_unstable ${{ matrix.run.RUSTFLAGS }}
RUSTDOCFLAGS: --cfg docsrs --cfg tokio_unstable -Dwarnings ${{ matrix.run.RUSTDOCFLAGS }}
loom-compile:
name: build loom tests
@@ -858,6 +843,56 @@ jobs:
run: cargo test --features full
working-directory: hyper
test-quinn:
name: Test Quinn
needs: basics
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- windows-latest
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_stable }}
- name: Clone Quinn
run: git clone https://github.com/quinn-rs/quinn.git
- name: Checkout the latest release because HEAD maybe contains breakage.
run: |
set -x
tag=$(git describe --abbrev=0 --tags)
git checkout "${tag}"
working-directory: quinn
- name: Patch Quinn to use tokio from this repository
run: |
set -x
echo '[patch.crates-io]' >>Cargo.toml
echo 'tokio = { path = "../tokio" }' >>Cargo.toml
git diff
working-directory: quinn
- uses: Swatinem/rust-cache@v2
with:
# The cargo workspaces and target directory configuration.
# These entries are separated by newlines and have the form
# `$workspace -> $target`. The `$target` part is treated as a directory
# relative to the `$workspace` and defaults to "target" if not explicitly given.
# default: ". -> target"
workspaces: "./quinn"
- name: Test Quinn
working-directory: quinn
env:
RUSTFLAGS: ""
run: cargo test
x86_64-fortanix-unknown-sgx:
name: build tokio for x86_64-fortanix-unknown-sgx
needs: basics
@@ -896,10 +931,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
- name: Install Rust 1.81
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_stable }}
toolchain: 1.81
- name: Install wasm-pack
uses: taiki-e/install-action@wasm-pack
@@ -908,17 +943,22 @@ jobs:
run: wasm-pack test --node -- --features "macros sync"
working-directory: tokio
wasm32-wasi:
name: wasm32-wasi
wasm32-wasip1:
name: ${{ matrix.target }}
needs: basics
runs-on: ubuntu-latest
strategy:
matrix:
target:
- wasm32-wasip1
- wasm32-wasip1-threads
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_stable }}
targets: wasm32-wasi
targets: ${{ matrix.target }}
# Install dependencies
- name: Install cargo-hack, wasmtime, and cargo-wasi
@@ -928,28 +968,40 @@ jobs:
- uses: Swatinem/rust-cache@v2
- name: WASI test tokio full
run: cargo test -p tokio --target wasm32-wasi --features full
run: cargo test -p tokio --target ${{ matrix.target }} --features full
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
CARGO_TARGET_WASM32_WASIP1_RUNNER: "wasmtime run --"
CARGO_TARGET_WASM32_WASIP1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864
- name: WASI test tokio-util full
run: cargo test -p tokio-util --target wasm32-wasi --features full
run: cargo test -p tokio-util --target ${{ matrix.target }} --features full
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
CARGO_TARGET_WASM32_WASIP1_RUNNER: "wasmtime run --"
CARGO_TARGET_WASM32_WASIP1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864
- name: WASI test tokio-stream
run: cargo test -p tokio-stream --target wasm32-wasi --features time,net,io-util,sync
run: cargo test -p tokio-stream --target ${{ matrix.target }} --features time,net,io-util,sync
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
CARGO_TARGET_WASM32_WASIP1_RUNNER: "wasmtime run --"
CARGO_TARGET_WASM32_WASIP1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864
- 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
if: matrix.target == 'wasm32-wasip1'
working-directory: tests-integration
- name: test tests-integration --features wasi-threads-rt
run: cargo test --target ${{ matrix.target }} --features wasi-threads-rt
if: matrix.target == 'wasm32-wasip1-threads'
working-directory: tests-integration
env:
CARGO_TARGET_WASM32_WASIP1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864
check-external-types:
name: check-external-types (${{ matrix.os }})
needs: basics
@@ -962,7 +1014,7 @@ jobs:
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-10-21
- nightly-2024-06-30
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ matrix.rust }}
@@ -973,11 +1025,28 @@ jobs:
- name: Install cargo-check-external-types
uses: taiki-e/cache-cargo-install-action@v1
with:
tool: [email protected]0
tool: [email protected]3
- name: check-external-types
run: cargo check-external-types --all-features
working-directory: tokio
check-unexpected-lints-cfgs:
name: check unexpected lints and cfgs
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_nightly }}
- name: don't allow warnings
run: sed -i '/#!\[allow(unknown_lints, unexpected_cfgs)\]/d' */src/lib.rs */tests/*.rs
- name: check for unknown lints and cfgs
run: cargo check --all-features --tests
env:
RUSTFLAGS: -Dwarnings --check-cfg=cfg(loom,tokio_unstable,tokio_taskdump,fuzzing,mio_unsupported_force_poll_poll,tokio_internal_mt_counters,fs,tokio_no_parking_lot,tokio_no_tuning_tests) -Funexpected_cfgs -Funknown_lints
check-fuzzing:
name: check-fuzzing
needs: basics
@@ -1016,16 +1085,22 @@ jobs:
- name: Make sure dictionary words are sorted and unique
run: |
# `sed` removes the first line (number of words) and
# the last line (new line).
#
# the last line (new line).
#
# `sort` makes sure everything in between is sorted
# and contains no duplicates.
#
#
# Since `sort` is sensitive to locale, we set it
# using LC_ALL to en_US.UTF8 to be consistent in different
# environments.
sed '1d; $d' spellcheck.dic | LC_ALL=en_US.UTF8 sort -uc
(
sed '1d; $d' spellcheck.dic | LC_ALL=en_US.UTF8 sort -uc
) || {
echo "Dictionary is not in sorted order. Correct order is:"
LC_ALL=en_US.UTF8 sort -u <(sed '1d; $d' spellcheck.dic)
false
}
- name: Run cargo-spellcheck
run: cargo spellcheck --code 1
+3 -12
View File
@@ -16,17 +16,8 @@ permissions:
contents: read
jobs:
security-audit:
cargo-deny:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v4
- name: Install cargo-audit
run: cargo install cargo-audit
- name: Generate lockfile
run: cargo generate-lockfile
- name: Audit dependencies
run: cargo audit
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
+1 -1
View File
@@ -13,7 +13,7 @@ env:
RUSTFLAGS: -Dwarnings
RUST_BACKTRACE: 1
# Change to specific Rust release to pin
rust_stable: stable
rust_stable: 1.82
permissions:
contents: read
+21 -13
View File
@@ -149,23 +149,31 @@ When updating this, also update:
-->
```
cargo +1.76 clippy --all --tests --all-features
cargo +1.77 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:
When building documentation, a simple `cargo doc` is not sufficient. To produce
documentation equivalent to what will be produced in docs.rs's builds of Tokio's
docs, please use:
```
RUSTDOCFLAGS="--cfg docsrs" RUSTFLAGS="--cfg docsrs" cargo +nightly doc --all-features
RUSTDOCFLAGS="--cfg docsrs --cfg tokio_unstable" RUSTFLAGS="--cfg docsrs --cfg tokio_unstable" cargo +nightly doc --all-features [--open]
```
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:
This turns on indicators to display the Cargo features required for
conditionally compiled APIs in Tokio, and it enables documentation of unstable
Tokio features. Notice that it is necessary to pass cfg flags to both RustDoc
*and* rustc.
There is a more concise way to build docs.rs-equivalent docs by using [`cargo
docs-rs`], which reads the above documentation flags out of Tokio's Cargo.toml
as docs.rs itself does.
[`cargo docs-rs`]: https://github.com/dtolnay/cargo-docs-rs
```
RUSTDOCFLAGS="--cfg docsrs --cfg tokio_unstable" RUSTFLAGS="--cfg docsrs --cfg tokio_unstable" cargo +nightly doc --all-features
cargo install --locked cargo-docs-rs
cargo +nightly docs-rs [--open]
```
The `cargo fmt` command does not work on the Tokio codebase. You can use the
@@ -192,8 +200,8 @@ run loom tests that test unstable features.
You can run miri tests with
```
MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-tag-raw-pointers" \
cargo +nightly miri test --features full --lib
MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields" \
cargo +nightly miri test --features full --lib --tests
```
### Performing spellcheck on tokio codebase
@@ -253,7 +261,7 @@ 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`
`cargo install --locked cargo-fuzz`
To list the available fuzzing harnesses you can run;
@@ -261,7 +269,7 @@ To list the available fuzzing harnesses you can run;
$ cd tokio
$ cargo fuzz list
fuzz_linked_list
````
```
Running a fuzz test is as simple as;
-1
View File
@@ -17,4 +17,3 @@ members = [
[workspace.metadata.spellcheck]
config = "spellcheck.toml"
+18 -22
View File
@@ -1,25 +1,21 @@
Copyright (c) 2023 Tokio Contributors
MIT License
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
Copyright (c) Tokio Contributors
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+6 -4
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.37.0", features = ["full"] }
tokio = { version = "1.42.0", features = ["full"] }
```
Then, on your main.rs:
@@ -186,12 +186,13 @@ When updating this, also update:
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.63.
released at least six months ago. The current MSRV is 1.70.
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.30 to now - Rust 1.63
* 1.39 to now - Rust 1.70
* 1.30 to 1.38 - Rust 1.63
* 1.27 to 1.29 - Rust 1.56
* 1.17 to 1.26 - Rust 1.49
* 1.15 to 1.16 - Rust 1.46
@@ -215,8 +216,8 @@ 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.32.x` - LTS release until September 2024. (MSRV 1.63)
* `1.36.x` - LTS release until March 2025. (MSRV 1.63)
* `1.38.x` - LTS release until July 2025. (MSRV 1.63)
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
@@ -236,6 +237,7 @@ tokio = { version = "~1.32", features = [...] }
* `1.18.x` - LTS release until June 2023.
* `1.20.x` - LTS release until September 2023.
* `1.25.x` - LTS release until March 2024.
* `1.32.x` - LTS release until September 2024.
## License
+7 -2
View File
@@ -3,6 +3,7 @@ name = "benches"
version = "0.0.0"
publish = false
edition = "2021"
license = "MIT"
[features]
test-util = ["tokio/test-util"]
@@ -12,11 +13,10 @@ tokio = { version = "1.5.0", path = "../tokio", features = ["full"] }
criterion = "0.5.1"
rand = "0.8"
rand_chacha = "0.3"
num_cpus = "1.16.0"
[dev-dependencies]
tokio-util = { version = "0.7.0", path = "../tokio-util", features = ["full"] }
tokio-stream = { path = "../tokio-stream" }
tokio-stream = { version = "0.1", path = "../tokio-stream" }
[target.'cfg(unix)'.dependencies]
libc = "0.2.42"
@@ -90,3 +90,8 @@ harness = false
name = "time_now"
path = "time_now.rs"
harness = false
[[bench]]
name = "time_timeout"
path = "time_timeout.rs"
harness = false
+1 -1
View File
@@ -37,7 +37,7 @@ fn create_medium<const SIZE: usize>(g: &mut BenchmarkGroup<WallTime>) {
fn send_data<T: Default, const SIZE: usize>(g: &mut BenchmarkGroup<WallTime>, prefix: &str) {
let rt = rt();
g.bench_function(format!("{}_{}", prefix, SIZE), |b| {
g.bench_function(format!("{prefix}_{SIZE}"), |b| {
b.iter(|| {
let (tx, mut rx) = mpsc::channel::<T>(SIZE);
+109
View File
@@ -0,0 +1,109 @@
use std::time::{Duration, Instant};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use tokio::{
runtime::Runtime,
time::{sleep, timeout},
};
// a very quick async task, but might timeout
async fn quick_job() -> usize {
1
}
fn build_run_time(workers: usize) -> Runtime {
if workers == 1 {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
} else {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.worker_threads(workers)
.build()
.unwrap()
}
}
fn single_thread_scheduler_timeout(c: &mut Criterion) {
do_timeout_test(c, 1, "single_thread_timeout");
}
fn multi_thread_scheduler_timeout(c: &mut Criterion) {
do_timeout_test(c, 8, "multi_thread_timeout-8");
}
fn do_timeout_test(c: &mut Criterion, workers: usize, name: &str) {
let runtime = build_run_time(workers);
c.bench_function(name, |b| {
b.iter_custom(|iters| {
let start = Instant::now();
runtime.block_on(async {
black_box(spawn_timeout_job(iters as usize, workers)).await;
});
start.elapsed()
})
});
}
async fn spawn_timeout_job(iters: usize, procs: usize) {
let mut handles = Vec::with_capacity(procs);
for _ in 0..procs {
handles.push(tokio::spawn(async move {
for _ in 0..iters / procs {
let h = timeout(Duration::from_secs(1), quick_job());
assert_eq!(black_box(h.await.unwrap()), 1);
}
}));
}
for handle in handles {
handle.await.unwrap();
}
}
fn single_thread_scheduler_sleep(c: &mut Criterion) {
do_sleep_test(c, 1, "single_thread_sleep");
}
fn multi_thread_scheduler_sleep(c: &mut Criterion) {
do_sleep_test(c, 8, "multi_thread_sleep-8");
}
fn do_sleep_test(c: &mut Criterion, workers: usize, name: &str) {
let runtime = build_run_time(workers);
c.bench_function(name, |b| {
b.iter_custom(|iters| {
let start = Instant::now();
runtime.block_on(async {
black_box(spawn_sleep_job(iters as usize, workers)).await;
});
start.elapsed()
})
});
}
async fn spawn_sleep_job(iters: usize, procs: usize) {
let mut handles = Vec::with_capacity(procs);
for _ in 0..procs {
handles.push(tokio::spawn(async move {
for _ in 0..iters / procs {
let _h = black_box(sleep(Duration::from_secs(1)));
}
}));
}
for handle in handles {
handle.await.unwrap();
}
}
criterion_group!(
timeout_benchmark,
single_thread_scheduler_timeout,
multi_thread_scheduler_timeout,
single_thread_scheduler_sleep,
multi_thread_scheduler_sleep
);
criterion_main!(timeout_benchmark);
+21
View File
@@ -0,0 +1,21 @@
# https://embarkstudios.github.io/cargo-deny/cli/init.html
[graph]
all-features = true
[licenses]
allow = [
"MIT",
"Apache-2.0",
]
exceptions = [
{ allow = ["Unicode-3.0", "Unicode-DFS-2016"], crate = "unicode-ident" },
]
[bans]
multiple-versions = "allow"
wildcards = "deny"
[sources]
unknown-registry = "deny"
unknown-git = "deny"
+2 -1
View File
@@ -3,6 +3,7 @@ name = "examples"
version = "0.0.0"
publish = false
edition = "2021"
license = "MIT"
# If you copy one of the examples into a new project, you should be using
# [dependencies] instead, and delete the **path**.
@@ -25,7 +26,7 @@ once_cell = "1.5.2"
rand = "0.8.3"
[target.'cfg(windows)'.dev-dependencies.windows-sys]
version = "0.48"
version = "0.52"
[[example]]
name = "chat"
+3 -3
View File
@@ -193,7 +193,7 @@ async fn process(
// A client has connected, let's let everyone know.
{
let mut state = state.lock().await;
let msg = format!("{} has joined the chat", username);
let msg = format!("{username} has joined the chat");
tracing::info!("{}", msg);
state.broadcast(addr, &msg).await;
}
@@ -210,7 +210,7 @@ async fn process(
// broadcast this message to the other users.
Some(Ok(msg)) => {
let mut state = state.lock().await;
let msg = format!("{}: {}", username, msg);
let msg = format!("{username}: {msg}");
state.broadcast(addr, &msg).await;
}
@@ -234,7 +234,7 @@ async fn process(
let mut state = state.lock().await;
state.peers.remove(&addr);
let msg = format!("{} has left the chat", username);
let msg = format!("{username} has left the chat");
tracing::info!("{}", msg);
state.broadcast(addr, &msg).await;
}
+1 -1
View File
@@ -77,7 +77,7 @@ mod tcp {
//BytesMut into Bytes
Ok(i) => future::ready(Some(i.freeze())),
Err(e) => {
println!("failed to read from socket; error={}", e);
println!("failed to read from socket; error={e}");
future::ready(None)
}
})
+2
View File
@@ -1,3 +1,5 @@
#![allow(unknown_lints, unexpected_cfgs)]
//! 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.
+1 -1
View File
@@ -38,7 +38,7 @@ impl Server {
if let Some((size, peer)) = to_send {
let amt = socket.send_to(&buf[..size], &peer).await?;
println!("Echoed {}/{} bytes to {}", amt, size, peer);
println!("Echoed {amt}/{size} bytes to {peer}");
}
// If we're here then `to_send` is `None`, so we take a look for the
+1 -1
View File
@@ -40,7 +40,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
// connections. This TCP listener is bound to the address we determined
// above and must be associated with an event loop.
let listener = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
println!("Listening on: {addr}");
loop {
// Asynchronously wait for an inbound socket.
+3 -3
View File
@@ -75,7 +75,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// to our event loop. After the socket's created we inform that we're ready
// to go and start accepting connections.
let listener = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
println!("Listening on: {addr}");
loop {
// Asynchronously wait for an inbound socket.
@@ -96,8 +96,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// The stream will return None once the client disconnects.
while let Some(message) = framed.next().await {
match message {
Ok(bytes) => println!("bytes: {:?}", bytes),
Err(err) => println!("Socket closed with error: {:?}", err),
Ok(bytes) => println!("bytes: {bytes:?}"),
Err(err) => println!("Socket closed with error: {err:?}"),
}
}
println!("Socket received FIN packet and closed connection");
+3 -3
View File
@@ -38,8 +38,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
.nth(2)
.unwrap_or_else(|| "127.0.0.1:8080".to_string());
println!("Listening on: {}", listen_addr);
println!("Proxying to: {}", server_addr);
println!("Listening on: {listen_addr}");
println!("Proxying to: {server_addr}");
let listener = TcpListener::bind(listen_addr).await?;
@@ -50,7 +50,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
copy_bidirectional(&mut inbound, &mut outbound)
.map(|r| {
if let Err(e) = r {
println!("Failed to transfer; error={}", e);
println!("Failed to transfer; error={e}");
}
})
.await
+9 -9
View File
@@ -90,7 +90,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
.unwrap_or_else(|| "127.0.0.1:8080".to_string());
let listener = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
println!("Listening on: {addr}");
// Create the shared state of this server that will be shared amongst all
// clients. We populate the initial database and then create the `Database`
@@ -131,11 +131,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
let response = response.serialize();
if let Err(e) = lines.send(response.as_str()).await {
println!("error on sending response; error = {:?}", e);
println!("error on sending response; error = {e:?}");
}
}
Err(e) => {
println!("error on decoding from socket; error = {:?}", e);
println!("error on decoding from socket; error = {e:?}");
}
}
}
@@ -143,7 +143,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
// The connection will be closed at this point as `lines.next()` has returned `None`.
});
}
Err(e) => println!("error accepting socket; error = {:?}", e),
Err(e) => println!("error accepting socket; error = {e:?}"),
}
}
}
@@ -162,7 +162,7 @@ fn handle_request(line: &str, db: &Arc<Database>) -> Response {
value: value.clone(),
},
None => Response::Error {
msg: format!("no key {}", key),
msg: format!("no key {key}"),
},
},
Request::Set { key, value } => {
@@ -203,7 +203,7 @@ impl Request {
value: value.to_string(),
})
}
Some(cmd) => Err(format!("unknown command: {}", cmd)),
Some(cmd) => Err(format!("unknown command: {cmd}")),
None => Err("empty input".into()),
}
}
@@ -212,13 +212,13 @@ impl Request {
impl Response {
fn serialize(&self) -> String {
match *self {
Response::Value { ref key, ref value } => format!("{} = {}", key, value),
Response::Value { ref key, ref value } => format!("{key} = {value}"),
Response::Set {
ref key,
ref value,
ref previous,
} => format!("set {} = `{}`, previous: {:?}", key, value, previous),
Response::Error { ref msg } => format!("error: {}", msg),
} => format!("set {key} = `{value}`, previous: {previous:?}"),
Response::Error { ref msg } => format!("error: {msg}"),
}
}
}
+5 -5
View File
@@ -31,13 +31,13 @@ async fn main() -> Result<(), Box<dyn Error>> {
.nth(1)
.unwrap_or_else(|| "127.0.0.1:8080".to_string());
let server = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
println!("Listening on: {addr}");
loop {
let (stream, _) = server.accept().await?;
tokio::spawn(async move {
if let Err(e) = process(stream).await {
println!("failed to process connection; error = {}", e);
println!("failed to process connection; error = {e}");
}
});
}
@@ -159,7 +159,7 @@ impl Decoder for Http {
let mut parsed_headers = [httparse::EMPTY_HEADER; 16];
let mut r = httparse::Request::new(&mut parsed_headers);
let status = r.parse(src).map_err(|e| {
let msg = format!("failed to parse http request: {:?}", e);
let msg = format!("failed to parse http request: {e:?}");
io::Error::new(io::ErrorKind::Other, msg)
})?;
@@ -259,11 +259,11 @@ mod date {
unix_date: u64,
}
thread_local!(static LAST: RefCell<LastRenderedNow> = RefCell::new(LastRenderedNow {
thread_local!(static LAST: RefCell<LastRenderedNow> = const { RefCell::new(LastRenderedNow {
bytes: [0; 128],
amt: 0,
unix_date: 0,
}));
}) });
impl fmt::Display for Now {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+1 -1
View File
@@ -46,7 +46,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Run both futures simultaneously of `a` and `b` sending messages back and forth.
match tokio::try_join!(a, b) {
Err(e) => println!("an error occurred; error = {:?}", e),
Err(e) => println!("an error occurred; error = {e:?}"),
_ => println!("done!"),
}
+12 -1
View File
@@ -1,4 +1,4 @@
283
292
&
+
<
@@ -12,12 +12,17 @@
0xA
0xD
100ms
100ns
10ms
10μs
~12
120s
12.5%
±1m
±1ms
1ms
1s
25%
250ms
2x
~4
@@ -34,6 +39,7 @@ amongst
api
APIs
async
atomics
awaitable
backend
backpressure
@@ -98,6 +104,7 @@ errored
EWMA
expirations
fcntl
fd
fd's
FIFOs
filename
@@ -114,9 +121,11 @@ GID
goroutines
Growable
gzip
H2
hashmaps
HashMaps
hashsets
HdrHistogram
ie
Illumos
impl
@@ -131,6 +140,7 @@ io
IOCP
iOS
IOs
io_uring
IP
IPv4
IPv6
@@ -149,6 +159,7 @@ metadata
mio
Mio
mio's
miri
misconfigured
mock's
mpmc
+2 -1
View File
@@ -3,12 +3,13 @@ name = "stress-test"
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
edition = "2021"
license = "MIT"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { path = "../tokio/", features = ["full"] }
tokio = { version = "1.0.0", path = "../tokio/", features = ["full"] }
[dev-dependencies]
rand = "0.8"
+9
View File
@@ -0,0 +1,9 @@
This is used for the `no-atomic-u64-test` ci check that verifies that Tokio
works even if the `AtomicU64` type is missing.
When increasing the nightly compiler version, you may need to regenerate this
target using the following command:
```
rustc +nightly -Z unstable-options --print target-spec-json --target i686-unknown-linux-gnu | grep -v 'is-builtin' | sed 's/"max-atomic-width": 64/"max-atomic-width": 32/' > target-specs/i686-unknown-linux-gnu.json
```
+14 -8
View File
@@ -1,29 +1,35 @@
{
"arch": "x86",
"cpu": "pentium4",
"crt-objects-fallback": "false",
"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",
"data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
"dynamic-linking": true,
"env": "gnu",
"has-rpath": true,
"has-thread-local": true,
"linker-flavor": "gnu-cc",
"llvm-target": "i686-unknown-linux-gnu",
"max-atomic-width": 32,
"metadata": {
"description": null,
"host_tools": null,
"std": null,
"tier": null
},
"os": "linux",
"position-independent-executables": true,
"pre-link-args": {
"gcc": [
"gnu-cc": [
"-m32"
],
"gnu-lld-cc": [
"-m32"
]
},
"relro-level": "full",
"stack-probes": {
"kind": "inline-or-call",
"min-llvm-version-for-inline": [
16,
0,
0
]
"kind": "inline"
},
"supported-sanitizers": [
"address"
+2 -1
View File
@@ -3,6 +3,7 @@ name = "tests-build"
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
edition = "2021"
license = "MIT"
publish = false
[features]
@@ -10,7 +11,7 @@ full = ["tokio/full"]
rt = ["tokio/rt", "tokio/macros"]
[dependencies]
tokio = { path = "../tokio", optional = true }
tokio = { version = "1.0.0", path = "../tokio", optional = true }
[dev-dependencies]
trybuild = "1.0"
+1 -1
View File
@@ -6,5 +6,5 @@ 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`
If any of the tests fail, you can pass `TRYBUILD=overwrite` to the `cargo test`
command that failed to have it regenerate the test output.
@@ -41,8 +41,31 @@ async fn test_crate_not_path_int() {}
#[tokio::test(crate = "456")]
async fn test_crate_not_path_invalid() {}
#[tokio::test(flavor = "multi_thread", unhandled_panic = "shutdown_runtime")]
async fn test_multi_thread_with_unhandled_panic() {}
#[tokio::test]
#[test]
async fn test_has_second_test_attr() {}
#[tokio::test]
#[::core::prelude::v1::test]
async fn test_has_second_test_attr_v1() {}
#[tokio::test]
#[core::prelude::rust_2015::test]
async fn test_has_second_test_attr_rust_2015() {}
#[tokio::test]
#[::std::prelude::rust_2018::test]
async fn test_has_second_test_attr_rust_2018() {}
#[tokio::test]
#[std::prelude::rust_2021::test]
async fn test_has_second_test_attr_rust_2021() {}
#[tokio::test]
#[tokio::test]
async fn test_has_generated_second_test_attr() {}
fn main() {}
@@ -1,95 +1,121 @@
error: the `async` keyword is missing from the function declaration
--> $DIR/macros_invalid_input.rs:6:1
--> tests/fail/macros_invalid_input.rs:6:1
|
6 | fn main_is_not_async() {}
| ^^
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`
--> $DIR/macros_invalid_input.rs:8:15
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`, `unhandled_panic`.
--> tests/fail/macros_invalid_input.rs:8:15
|
8 | #[tokio::main(foo)]
| ^^^
error: Must have specified ident
--> $DIR/macros_invalid_input.rs:11:15
--> tests/fail/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:15:1
--> tests/fail/macros_invalid_input.rs:15:1
|
15 | fn test_is_not_async() {}
| ^^
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`
--> $DIR/macros_invalid_input.rs:17:15
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`, `unhandled_panic`.
--> tests/fail/macros_invalid_input.rs:17:15
|
17 | #[tokio::test(foo)]
| ^^^
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`
--> $DIR/macros_invalid_input.rs:20:15
error: Unknown attribute foo is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`, `unhandled_panic`
--> tests/fail/macros_invalid_input.rs:20:15
|
20 | #[tokio::test(foo = 123)]
| ^^^^^^^^^
error: Failed to parse value of `flavor` as string.
--> $DIR/macros_invalid_input.rs:23:24
--> tests/fail/macros_invalid_input.rs:23:24
|
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:26:24
--> tests/fail/macros_invalid_input.rs:26:24
|
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:29:55
--> tests/fail/macros_invalid_input.rs:29:55
|
29 | #[tokio::test(flavor = "multi_thread", start_paused = false)]
| ^^^^^
error: Failed to parse value of `worker_threads` as integer.
--> $DIR/macros_invalid_input.rs:32:57
--> tests/fail/macros_invalid_input.rs:32:57
|
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:35:59
--> tests/fail/macros_invalid_input.rs:35:59
|
35 | #[tokio::test(flavor = "current_thread", worker_threads = 4)]
| ^
error: Failed to parse value of `crate` as path.
--> $DIR/macros_invalid_input.rs:38:23
--> tests/fail/macros_invalid_input.rs:38:23
|
38 | #[tokio::test(crate = 456)]
| ^^^
error: Failed to parse value of `crate` as path: "456"
--> $DIR/macros_invalid_input.rs:41:23
--> tests/fail/macros_invalid_input.rs:41:23
|
41 | #[tokio::test(crate = "456")]
| ^^^^^
error: second test attribute is supplied
--> $DIR/macros_invalid_input.rs:45:1
error: The `unhandled_panic` option requires the `current_thread` runtime flavor. Use `#[tokio::test(flavor = "current_thread")]`
--> tests/fail/macros_invalid_input.rs:44:58
|
45 | #[test]
44 | #[tokio::test(flavor = "multi_thread", unhandled_panic = "shutdown_runtime")]
| ^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> tests/fail/macros_invalid_input.rs:48:1
|
48 | #[test]
| ^^^^^^^
error: duplicated attribute
--> $DIR/macros_invalid_input.rs:45:1
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> tests/fail/macros_invalid_input.rs:52:1
|
45 | #[test]
| ^^^^^^^
52 | #[::core::prelude::v1::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> tests/fail/macros_invalid_input.rs:56:1
|
note: the lint level is defined here
--> $DIR/macros_invalid_input.rs:1:9
56 | #[core::prelude::rust_2015::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> tests/fail/macros_invalid_input.rs:60:1
|
1 | #![deny(duplicate_macro_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
60 | #[::std::prelude::rust_2018::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> tests/fail/macros_invalid_input.rs:64:1
|
64 | #[std::prelude::rust_2021::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> tests/fail/macros_invalid_input.rs:67:1
|
67 | #[tokio::test]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `tokio::test` (in Nightly builds, run with -Z macro-backtrace for more info)
+1
View File
@@ -1,4 +1,5 @@
#[test]
#[cfg_attr(miri, ignore)]
fn compile_fail_full() {
let t = trybuild::TestCases::new();
+4 -2
View File
@@ -3,6 +3,7 @@ name = "tests-integration"
version = "0.1.0"
authors = ["Tokio Contributors <[email protected]>"]
edition = "2021"
license = "MIT"
publish = false
[[bin]]
@@ -39,6 +40,7 @@ rt-process-signal = ["rt-net", "tokio/process", "tokio/signal"]
# This is an explicit feature so we can use `cargo hack` testing single features
# instead of all possible permutations.
wasi-rt = ["rt", "macros", "sync"]
wasi-threads-rt = ["wasi-rt", "rt-multi-thread"]
full = [
"macros",
@@ -54,8 +56,8 @@ rt = ["tokio/rt"]
rt-multi-thread = ["rt", "tokio/rt-multi-thread"]
[dependencies]
tokio = { path = "../tokio" }
tokio-test = { path = "../tokio-test", optional = true }
tokio = { version = "1.0.0", path = "../tokio" }
tokio-test = { version = "0.4", path = "../tokio-test", optional = true }
doc-comment = "0.3.1"
futures = { version = "0.3.0", features = ["async-await"] }
bytes = "1.0.0"
+1 -1
View File
@@ -1,4 +1,4 @@
use futures::future::poll_fn;
use std::future::poll_fn;
fn main() {
let rt = tokio::runtime::Builder::new_multi_thread()
+1 -5
View File
@@ -1,8 +1,4 @@
#![cfg(all(
feature = "macros",
feature = "rt-multi-thread",
not(target_os = "wasi")
))]
#![cfg(all(feature = "macros", feature = "rt-multi-thread"))]
#[tokio::main]
async fn basic_main() -> usize {
+4 -1
View File
@@ -4,7 +4,10 @@ use futures::channel::oneshot;
use futures::executor::block_on;
use std::thread;
#[cfg_attr(target_os = "wasi", ignore = "WASI: std::thread::spawn not supported")]
#[cfg_attr(
not(feature = "rt-multi-thread"),
ignore = "WASI: std::thread::spawn not supported"
)]
#[test]
fn join_with_select() {
block_on(async {
+4 -3
View File
@@ -1,5 +1,5 @@
#![warn(rust_2018_idioms)]
#![cfg(all(feature = "full", not(target_os = "wasi")))]
#![cfg(all(feature = "full", not(target_os = "wasi"), not(miri)))]
use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};
use tokio::join;
@@ -10,6 +10,7 @@ use futures::future::{self, FutureExt};
use std::env;
use std::io;
use std::process::{ExitStatus, Stdio};
use std::task::ready;
fn cat() -> Command {
let mut cmd = Command::new(env!("CARGO_BIN_EXE_test-cat"));
@@ -205,13 +206,13 @@ async fn vectored_writes() {
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 {
std::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))?;
let n = ready!(Pin::new(&mut stdin).poll_write_vectored(cx, &slices))?;
writes_completed += 1;
input.advance(n);
})
+14
View File
@@ -1,3 +1,17 @@
# 2.4.0 (July 22nd, 2024)
- msrv: increase MSRV to 1.70 ([#6645])
- macros: allow `unhandled_panic` behavior for `#[tokio::main]` and `#[tokio::test]` ([#6593])
[#6593]: https://github.com/tokio-rs/tokio/pull/6593
[#6645]: https://github.com/tokio-rs/tokio/pull/6645
# 2.3.0 (May 30th, 2024)
- macros: make `#[tokio::test]` append `#[test]` at the end of the attribute list ([#6497])
[#6497]: https://github.com/tokio-rs/tokio/pull/6497
# 2.2.0 (November 19th, 2023)
### Changed
+2 -2
View File
@@ -4,9 +4,9 @@ name = "tokio-macros"
# - Remove path dependencies
# - Update CHANGELOG.md.
# - Create "tokio-macros-1.x.y" git tag.
version = "2.2.0"
version = "2.4.0"
edition = "2021"
rust-version = "1.63"
rust-version = "1.70"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
+2 -27
View File
@@ -1,32 +1,7 @@
Copyright (c) 2023 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
The MIT License (MIT)
MIT License
Copyright (c) 2019 Yoshua Wuyts
Copyright (c) Tokio Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+120 -24
View File
@@ -20,7 +20,32 @@ impl RuntimeFlavor {
"single_thread" => Err("The single threaded runtime flavor is called `current_thread`.".to_string()),
"basic_scheduler" => Err("The `basic_scheduler` runtime flavor has been renamed to `current_thread`.".to_string()),
"threaded_scheduler" => Err("The `threaded_scheduler` runtime flavor has been renamed to `multi_thread`.".to_string()),
_ => Err(format!("No such runtime flavor `{}`. The runtime flavors are `current_thread` and `multi_thread`.", s)),
_ => Err(format!("No such runtime flavor `{s}`. The runtime flavors are `current_thread` and `multi_thread`.")),
}
}
}
#[derive(Clone, Copy, PartialEq)]
enum UnhandledPanic {
Ignore,
ShutdownRuntime,
}
impl UnhandledPanic {
fn from_str(s: &str) -> Result<UnhandledPanic, String> {
match s {
"ignore" => Ok(UnhandledPanic::Ignore),
"shutdown_runtime" => Ok(UnhandledPanic::ShutdownRuntime),
_ => Err(format!("No such unhandled panic behavior `{s}`. The unhandled panic behaviors are `ignore` and `shutdown_runtime`.")),
}
}
fn into_tokens(self, crate_path: &TokenStream) -> TokenStream {
match self {
UnhandledPanic::Ignore => quote! { #crate_path::runtime::UnhandledPanic::Ignore },
UnhandledPanic::ShutdownRuntime => {
quote! { #crate_path::runtime::UnhandledPanic::ShutdownRuntime }
}
}
}
}
@@ -30,6 +55,7 @@ struct FinalConfig {
worker_threads: Option<usize>,
start_paused: Option<bool>,
crate_name: Option<Path>,
unhandled_panic: Option<UnhandledPanic>,
}
/// Config used in case of the attribute not being able to build a valid config
@@ -38,6 +64,7 @@ const DEFAULT_ERROR_CONFIG: FinalConfig = FinalConfig {
worker_threads: None,
start_paused: None,
crate_name: None,
unhandled_panic: None,
};
struct Configuration {
@@ -48,6 +75,7 @@ struct Configuration {
start_paused: Option<(bool, Span)>,
is_test: bool,
crate_name: Option<Path>,
unhandled_panic: Option<(UnhandledPanic, Span)>,
}
impl Configuration {
@@ -63,6 +91,7 @@ impl Configuration {
start_paused: None,
is_test,
crate_name: None,
unhandled_panic: None,
}
}
@@ -117,6 +146,25 @@ impl Configuration {
Ok(())
}
fn set_unhandled_panic(
&mut self,
unhandled_panic: syn::Lit,
span: Span,
) -> Result<(), syn::Error> {
if self.unhandled_panic.is_some() {
return Err(syn::Error::new(
span,
"`unhandled_panic` set multiple times.",
));
}
let unhandled_panic = parse_string(unhandled_panic, span, "unhandled_panic")?;
let unhandled_panic =
UnhandledPanic::from_str(&unhandled_panic).map_err(|err| syn::Error::new(span, err))?;
self.unhandled_panic = Some((unhandled_panic, span));
Ok(())
}
fn macro_name(&self) -> &'static str {
if self.is_test {
"tokio::test"
@@ -163,11 +211,24 @@ impl Configuration {
(_, None) => None,
};
let unhandled_panic = match (flavor, self.unhandled_panic) {
(F::Threaded, Some((_, unhandled_panic_span))) => {
let msg = format!(
"The `unhandled_panic` option requires the `current_thread` runtime flavor. Use `#[{}(flavor = \"current_thread\")]`",
self.macro_name(),
);
return Err(syn::Error::new(unhandled_panic_span, msg));
}
(F::CurrentThread, Some((unhandled_panic, _))) => Some(unhandled_panic),
(_, None) => None,
};
Ok(FinalConfig {
crate_name: self.crate_name.clone(),
flavor,
worker_threads,
start_paused,
unhandled_panic,
})
}
}
@@ -178,12 +239,12 @@ fn parse_int(int: syn::Lit, span: Span, field: &str) -> Result<usize, syn::Error
Ok(value) => Ok(value),
Err(e) => Err(syn::Error::new(
span,
format!("Failed to parse value of `{}` as integer: {}", field, e),
format!("Failed to parse value of `{field}` as integer: {e}"),
)),
},
_ => Err(syn::Error::new(
span,
format!("Failed to parse value of `{}` as integer.", field),
format!("Failed to parse value of `{field}` as integer."),
)),
}
}
@@ -194,7 +255,7 @@ fn parse_string(int: syn::Lit, span: Span, field: &str) -> Result<String, syn::E
syn::Lit::Verbatim(s) => Ok(s.to_string()),
_ => Err(syn::Error::new(
span,
format!("Failed to parse value of `{}` as string.", field),
format!("Failed to parse value of `{field}` as string."),
)),
}
}
@@ -214,7 +275,7 @@ fn parse_path(lit: syn::Lit, span: Span, field: &str) -> Result<Path, syn::Error
}
_ => Err(syn::Error::new(
span,
format!("Failed to parse value of `{}` as path.", field),
format!("Failed to parse value of `{field}` as path."),
)),
}
}
@@ -224,7 +285,7 @@ fn parse_bool(bool: syn::Lit, span: Span, field: &str) -> Result<bool, syn::Erro
syn::Lit::Bool(b) => Ok(b.value),
_ => Err(syn::Error::new(
span,
format!("Failed to parse value of `{}` as bool.", field),
format!("Failed to parse value of `{field}` as bool."),
)),
}
}
@@ -275,10 +336,13 @@ fn build_config(
"crate" => {
config.set_crate_name(lit.clone(), syn::spanned::Spanned::span(lit))?;
}
"unhandled_panic" => {
config
.set_unhandled_panic(lit.clone(), syn::spanned::Spanned::span(lit))?;
}
name => {
let msg = format!(
"Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`",
name,
"Unknown attribute {name} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`, `unhandled_panic`",
);
return Err(syn::Error::new_spanned(namevalue, msg));
}
@@ -293,21 +357,19 @@ fn build_config(
let msg = match name.as_str() {
"threaded_scheduler" | "multi_thread" => {
format!(
"Set the runtime flavor with #[{}(flavor = \"multi_thread\")].",
macro_name
"Set the runtime flavor with #[{macro_name}(flavor = \"multi_thread\")]."
)
}
"basic_scheduler" | "current_thread" | "single_threaded" => {
format!(
"Set the runtime flavor with #[{}(flavor = \"current_thread\")].",
macro_name
"Set the runtime flavor with #[{macro_name}(flavor = \"current_thread\")]."
)
}
"flavor" | "worker_threads" | "start_paused" => {
format!("The `{}` attribute requires an argument.", name)
"flavor" | "worker_threads" | "start_paused" | "crate" | "unhandled_panic" => {
format!("The `{name}` attribute requires an argument.")
}
name => {
format!("Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`", name)
format!("Unknown attribute {name} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`, `unhandled_panic`.")
}
};
return Err(syn::Error::new_spanned(path, msg));
@@ -359,8 +421,12 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
if let Some(v) = config.start_paused {
rt = quote_spanned! {last_stmt_start_span=> #rt.start_paused(#v) };
}
if let Some(v) = config.unhandled_panic {
let unhandled_panic = v.into_tokens(&crate_path);
rt = quote_spanned! {last_stmt_start_span=> #rt.unhandled_panic(#unhandled_panic) };
}
let header = if is_test {
let generated_attrs = if is_test {
quote! {
#[::core::prelude::v1::test]
}
@@ -369,8 +435,9 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
};
let body_ident = quote! { body };
// This explicit `return` is intentional. See tokio-rs/tokio#4636
let last_block = quote_spanned! {last_stmt_end_span=>
#[allow(clippy::expect_used, clippy::diverging_sub_expression)]
#[allow(clippy::expect_used, clippy::diverging_sub_expression, clippy::needless_return)]
{
return #rt
.enable_all()
@@ -410,7 +477,7 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
}
};
input.into_tokens(header, body, last_block)
input.into_tokens(generated_attrs, body, last_block)
}
fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
@@ -418,7 +485,6 @@ fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenS
tokens
}
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub(crate) fn main(args: TokenStream, item: TokenStream, rt_multi_thread: bool) -> TokenStream {
// 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
@@ -443,6 +509,35 @@ pub(crate) fn main(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
}
}
// Check whether given attribute is a test attribute of forms:
// * `#[test]`
// * `#[core::prelude::*::test]` or `#[::core::prelude::*::test]`
// * `#[std::prelude::*::test]` or `#[::std::prelude::*::test]`
fn is_test_attribute(attr: &Attribute) -> bool {
let path = match &attr.meta {
syn::Meta::Path(path) => path,
_ => return false,
};
let candidates = [
["core", "prelude", "*", "test"],
["std", "prelude", "*", "test"],
];
if path.leading_colon.is_none()
&& path.segments.len() == 1
&& path.segments[0].arguments.is_none()
&& path.segments[0].ident == "test"
{
return true;
} else if path.segments.len() != candidates[0].len() {
return false;
}
candidates.into_iter().any(|segments| {
path.segments.iter().zip(segments).all(|(segment, path)| {
segment.arguments.is_none() && (path == "*" || segment.ident == path)
})
})
}
pub(crate) fn test(args: TokenStream, item: TokenStream, rt_multi_thread: bool) -> TokenStream {
// 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
@@ -451,8 +546,8 @@ pub(crate) fn test(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
Ok(it) => it,
Err(e) => return token_stream_with_error(item, e),
};
let config = if let Some(attr) = input.attrs().find(|attr| attr.meta.path().is_ident("test")) {
let msg = "second test attribute is supplied";
let config = if let Some(attr) = input.attrs().find(|attr| is_test_attribute(attr)) {
let msg = "second test attribute is supplied, consider removing or changing the order of your test attributes";
Err(syn::Error::new_spanned(attr, msg))
} else {
AttributeArgs::parse_terminated
@@ -493,13 +588,11 @@ impl ItemFn {
/// Convert our local function item into a token stream.
fn into_tokens(
self,
header: proc_macro2::TokenStream,
generated_attrs: 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);
@@ -513,6 +606,9 @@ impl ItemFn {
attr.to_tokens(&mut tokens);
}
// Add generated macros at the end, so macros processed later are aware of them.
generated_attrs.to_tokens(&mut tokens);
self.vis.to_tokens(&mut tokens);
self.sig.to_tokens(&mut tokens);
+99 -3
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![allow(clippy::needless_doctest_main)]
#![warn(
missing_debug_implementations,
@@ -201,8 +202,55 @@ use proc_macro::TokenStream;
/// })
/// }
/// ```
///
/// ### Configure unhandled panic behavior
///
/// Available options are `shutdown_runtime` and `ignore`. For more details, see
/// [`Builder::unhandled_panic`].
///
/// This option is only compatible with the `current_thread` runtime.
///
/// ```no_run
/// # #![allow(unknown_lints, unexpected_cfgs)]
/// #[cfg(tokio_unstable)]
/// #[tokio::main(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
/// async fn main() {
/// let _ = tokio::spawn(async {
/// panic!("This panic will shutdown the runtime.");
/// }).await;
/// }
/// # #[cfg(not(tokio_unstable))]
/// # fn main() { }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```no_run
/// # #![allow(unknown_lints, unexpected_cfgs)]
/// #[cfg(tokio_unstable)]
/// fn main() {
/// tokio::runtime::Builder::new_current_thread()
/// .enable_all()
/// .unhandled_panic(UnhandledPanic::ShutdownRuntime)
/// .build()
/// .unwrap()
/// .block_on(async {
/// let _ = tokio::spawn(async {
/// panic!("This panic will shutdown the runtime.");
/// }).await;
/// })
/// }
/// # #[cfg(not(tokio_unstable))]
/// # fn main() { }
/// ```
///
/// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
/// documentation on unstable features][unstable] for details on how to enable
/// Tokio's unstable features.
///
/// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
/// [unstable]: ../tokio/index.html#unstable-features
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
entry::main(args.into(), item.into(), true).into()
}
@@ -267,7 +315,6 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
/// }
/// ```
#[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.into(), item.into(), false).into()
}
@@ -365,7 +412,7 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
/// ### Set number of worker threads
///
/// ```no_run
/// #[tokio::test(flavor ="multi_thread", worker_threads = 2)]
/// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// async fn my_test() {
/// assert!(true);
/// }
@@ -424,6 +471,55 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
/// println!("Hello world");
/// }
/// ```
///
/// ### Configure unhandled panic behavior
///
/// Available options are `shutdown_runtime` and `ignore`. For more details, see
/// [`Builder::unhandled_panic`].
///
/// This option is only compatible with the `current_thread` runtime.
///
/// ```no_run
/// # #![allow(unknown_lints, unexpected_cfgs)]
/// #[cfg(tokio_unstable)]
/// #[tokio::test(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
/// async fn my_test() {
/// let _ = tokio::spawn(async {
/// panic!("This panic will shutdown the runtime.");
/// }).await;
/// }
/// # #[cfg(not(tokio_unstable))]
/// # fn main() { }
/// ```
///
/// Equivalent code not using `#[tokio::test]`
///
/// ```no_run
/// # #![allow(unknown_lints, unexpected_cfgs)]
/// #[cfg(tokio_unstable)]
/// #[test]
/// fn my_test() {
/// tokio::runtime::Builder::new_current_thread()
/// .enable_all()
/// .unhandled_panic(UnhandledPanic::ShutdownRuntime)
/// .build()
/// .unwrap()
/// .block_on(async {
/// let _ = tokio::spawn(async {
/// panic!("This panic will shutdown the runtime.");
/// }).await;
/// })
/// }
/// # #[cfg(not(tokio_unstable))]
/// # fn main() { }
/// ```
///
/// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
/// documentation on unstable features][unstable] for details on how to enable
/// Tokio's unstable features.
///
/// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
/// [unstable]: ../tokio/index.html#unstable-features
#[proc_macro_attribute]
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
entry::test(args.into(), item.into(), true).into()
+1 -1
View File
@@ -11,7 +11,7 @@ pub(crate) fn declare_output_enum(input: TokenStream) -> TokenStream {
};
let variants = (0..branches)
.map(|num| Ident::new(&format!("_{}", num), Span::call_site()))
.map(|num| Ident::new(&format!("_{num}"), Span::call_site()))
.collect::<Vec<_>>();
// Use a bitfield to track which futures completed
+12
View File
@@ -1,3 +1,15 @@
# 0.1.16 (September 5th, 2024)
This release bumps the MSRV of tokio-stream to 1.70.
- stream: add `next_many` and `poll_next_many` to `StreamMap` ([#6409])
- stream: make stream adapters public ([#6658])
- readme: add readme for tokio-stream ([#6456])
[#6409]: https://github.com/tokio-rs/tokio/pull/6409
[#6658]: https://github.com/tokio-rs/tokio/pull/6658
[#6456]: https://github.com/tokio-rs/tokio/pull/6456
# 0.1.15 (March 14th, 2024)
This release bumps the MSRV of tokio-stream to 1.63.
+3 -3
View File
@@ -4,9 +4,9 @@ name = "tokio-stream"
# - Remove path dependencies
# - Update CHANGELOG.md.
# - Create "tokio-stream-0.1.x" git tag.
version = "0.1.15"
version = "0.1.16"
edition = "2021"
rust-version = "1.63"
rust-version = "1.70"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
@@ -45,7 +45,7 @@ tokio-util = { version = "0.7.0", path = "../tokio-util", optional = true }
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" }
tokio-test = { version = "0.4", path = "../tokio-test" }
futures = { version = "0.3", default-features = false }
[package.metadata.docs.rs]
+18 -22
View File
@@ -1,25 +1,21 @@
Copyright (c) 2023 Tokio Contributors
MIT License
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
Copyright (c) Tokio Contributors
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+13
View File
@@ -0,0 +1,13 @@
# tokio-stream
Utilities to work with `Stream` and `tokio`.
## License
This project is licensed under the [MIT license](LICENSE).
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Tokio by you, shall be licensed as MIT, without any additional
terms or conditions.
+16 -4
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![allow(
clippy::cognitive_complexity,
clippy::large_enum_variant,
@@ -73,15 +74,26 @@
#[macro_use]
mod macros;
mod poll_fn;
pub(crate) use poll_fn::poll_fn;
pub mod wrappers;
mod stream_ext;
pub use stream_ext::{collect::FromStream, StreamExt};
/// Adapters for [`Stream`]s created by methods in [`StreamExt`].
pub mod adapters {
pub use crate::stream_ext::{
Chain, Filter, FilterMap, Fuse, Map, MapWhile, Merge, Peekable, Skip, SkipWhile, Take,
TakeWhile, Then,
};
cfg_time! {
pub use crate::stream_ext::{ChunksTimeout, Timeout, TimeoutRepeating};
}
}
cfg_time! {
pub use stream_ext::timeout::{Elapsed, Timeout};
#[deprecated = "Import those symbols from adapters instead"]
#[doc(hidden)]
pub use stream_ext::timeout::Timeout;
pub use stream_ext::timeout::Elapsed;
}
mod empty;
-9
View File
@@ -57,12 +57,3 @@ macro_rules! cfg_signal {
)*
}
}
macro_rules! ready {
($e:expr $(,)?) => {
match $e {
std::task::Poll::Ready(t) => t,
std::task::Poll::Pending => return std::task::Poll::Pending,
}
};
}
-35
View File
@@ -1,35 +0,0 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
pub(crate) struct PollFn<F> {
f: F,
}
pub(crate) fn poll_fn<T, F>(f: F) -> PollFn<F>
where
F: FnMut(&mut Context<'_>) -> Poll<T>,
{
PollFn { f }
}
impl<T, F> Future for PollFn<F>
where
F: FnMut(&mut Context<'_>) -> Poll<T>,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
// Safety: We never construct a `Pin<&mut F>` anywhere, so accessing `f`
// mutably in an unpinned way is sound.
//
// This use of unsafe cannot be replaced with the pin-project macro
// because:
// * If we put `#[pin]` on the field, then it gives us a `Pin<&mut F>`,
// which we can't use to call the closure.
// * If we don't put `#[pin]` on the field, then it makes `PollFn` be
// unconditionally `Unpin`, which we also don't want.
let me = unsafe { Pin::into_inner_unchecked(self) };
(me.f)(cx)
}
}
+16 -16
View File
@@ -8,66 +8,66 @@ mod any;
use any::AnyFuture;
mod chain;
use chain::Chain;
pub use chain::Chain;
pub(crate) mod collect;
use collect::{Collect, FromStream};
mod filter;
use filter::Filter;
pub use filter::Filter;
mod filter_map;
use filter_map::FilterMap;
pub use filter_map::FilterMap;
mod fold;
use fold::FoldFuture;
mod fuse;
use fuse::Fuse;
pub use fuse::Fuse;
mod map;
use map::Map;
pub use map::Map;
mod map_while;
use map_while::MapWhile;
pub use map_while::MapWhile;
mod merge;
use merge::Merge;
pub use merge::Merge;
mod next;
use next::Next;
mod skip;
use skip::Skip;
pub use skip::Skip;
mod skip_while;
use skip_while::SkipWhile;
pub use skip_while::SkipWhile;
mod take;
use take::Take;
pub use take::Take;
mod take_while;
use take_while::TakeWhile;
pub use take_while::TakeWhile;
mod then;
use then::Then;
pub use then::Then;
mod try_next;
use try_next::TryNext;
mod peekable;
use peekable::Peekable;
pub use peekable::Peekable;
cfg_time! {
pub(crate) mod timeout;
pub(crate) mod timeout_repeating;
use timeout::Timeout;
use timeout_repeating::TimeoutRepeating;
pub use timeout::Timeout;
pub use timeout_repeating::TimeoutRepeating;
use tokio::time::{Duration, Interval};
mod throttle;
use throttle::{throttle, Throttle};
mod chunks_timeout;
use chunks_timeout::ChunksTimeout;
pub use chunks_timeout::ChunksTimeout;
}
/// An extension trait for the [`Stream`] trait that provides a variety of
+2 -2
View File
@@ -3,7 +3,7 @@ use crate::Stream;
use core::future::Future;
use core::marker::PhantomPinned;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
@@ -42,7 +42,7 @@ where
// Take a maximum of 32 items from the stream before yielding.
for _ in 0..32 {
match futures_core::ready!(stream.as_mut().poll_next(cx)) {
match ready!(stream.as_mut().poll_next(cx)) {
Some(v) => {
if !(me.f)(v) {
return Poll::Ready(false);
+2 -2
View File
@@ -3,7 +3,7 @@ use crate::Stream;
use core::future::Future;
use core::marker::PhantomPinned;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
@@ -42,7 +42,7 @@ where
// Take a maximum of 32 items from the stream before yielding.
for _ in 0..32 {
match futures_core::ready!(stream.as_mut().poll_next(cx)) {
match ready!(stream.as_mut().poll_next(cx)) {
Some(v) => {
if (me.f)(v) {
return Poll::Ready(true);
+1 -1
View File
@@ -2,7 +2,7 @@ use crate::stream_ext::Fuse;
use crate::Stream;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
@@ -4,7 +4,7 @@ use tokio::time::{sleep, Sleep};
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
use std::time::Duration;
+1 -1
View File
@@ -4,7 +4,7 @@ use core::future::Future;
use core::marker::PhantomPinned;
use core::mem;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
// Do not export this struct until `FromStream` can be unsealed.
+1 -1
View File
@@ -2,7 +2,7 @@ use crate::Stream;
use core::fmt;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
+1 -1
View File
@@ -2,7 +2,7 @@ use crate::Stream;
use core::fmt;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
+1 -1
View File
@@ -3,7 +3,7 @@ use crate::Stream;
use core::future::Future;
use core::marker::PhantomPinned;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
+1 -1
View File
@@ -2,7 +2,7 @@ use crate::Stream;
use pin_project_lite::pin_project;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
pin_project! {
/// Stream returned by [`fuse()`][super::StreamExt::fuse].
+1 -1
View File
@@ -8,7 +8,7 @@ use crate::stream_ext::Fuse;
use crate::StreamExt;
pin_project! {
/// Stream returned by the [`chain`](super::StreamExt::peekable) method.
/// Stream returned by the [`peekable`](super::StreamExt::peekable) method.
pub struct Peekable<T: Stream> {
peek: Option<T::Item>,
#[pin]
+1 -1
View File
@@ -2,7 +2,7 @@ use crate::Stream;
use core::fmt;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
+1 -1
View File
@@ -2,7 +2,7 @@ use crate::Stream;
use core::fmt;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
+1 -1
View File
@@ -5,7 +5,7 @@ use tokio::time::{Duration, Instant, Sleep};
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};
use std::task::{self, ready, Poll};
use pin_project_lite::pin_project;
+1 -1
View File
@@ -4,7 +4,7 @@ use tokio::time::{Instant, Sleep};
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
use std::fmt;
use std::time::Duration;
@@ -3,7 +3,7 @@ use crate::{Elapsed, Stream};
use tokio::time::Interval;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::task::{ready, Context, Poll};
use pin_project_lite::pin_project;
pin_project! {
+7 -6
View File
@@ -1,9 +1,10 @@
use crate::{poll_fn, Stream};
use crate::Stream;
use std::borrow::Borrow;
use std::future::poll_fn;
use std::hash::Hash;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
/// Combine many streams into one, indexing each source stream with a unique
/// key.
@@ -467,10 +468,10 @@ impl<K, V> StreamMap<K, V> {
/// assert!(map.remove(&1).is_some());
/// assert!(map.remove(&1).is_none());
/// ```
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Hash + Eq,
Q: Hash + Eq + ?Sized,
{
for i in 0..self.entries.len() {
if self.entries[i].0.borrow() == k {
@@ -496,10 +497,10 @@ impl<K, V> StreamMap<K, V> {
/// assert_eq!(map.contains_key(&1), true);
/// assert_eq!(map.contains_key(&2), false);
/// ```
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
pub fn contains_key<Q>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
Q: Hash + Eq + ?Sized,
{
for i in 0..self.entries.len() {
if self.entries[i].0.borrow() == k {
+2 -2
View File
@@ -6,12 +6,12 @@ use futures_core::Stream;
use tokio_util::sync::ReusableBoxFuture;
use std::fmt;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
/// A wrapper around [`tokio::sync::broadcast::Receiver`] that implements [`Stream`].
///
/// [`tokio::sync::broadcast::Receiver`]: struct@tokio::sync::broadcast::Receiver
/// [`Stream`]: trait@crate::Stream
/// [`Stream`]: trait@futures_core::Stream
#[cfg_attr(docsrs, doc(cfg(feature = "sync")))]
pub struct BroadcastStream<T> {
inner: ReusableBoxFuture<'static, (Result<T, RecvError>, Receiver<T>)>,
+1 -1
View File
@@ -33,7 +33,7 @@ impl Stream for IntervalStream {
}
fn size_hint(&self) -> (usize, Option<usize>) {
(std::usize::MAX, None)
(usize::MAX, None)
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ use futures_core::Stream;
use tokio_util::sync::ReusableBoxFuture;
use std::fmt;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
use tokio::sync::watch::error::RecvError;
/// A wrapper around [`tokio::sync::watch::Receiver`] that implements [`Stream`].
+3
View File
@@ -15,18 +15,21 @@ fn require_unpin<T: Unpin>(_t: &T) {}
#[allow(dead_code)]
struct Invalid;
#[allow(unused)]
trait AmbiguousIfSend<A> {
fn some_item(&self) {}
}
impl<T: ?Sized> AmbiguousIfSend<()> for T {}
impl<T: ?Sized + Send> AmbiguousIfSend<Invalid> for T {}
#[allow(unused)]
trait AmbiguousIfSync<A> {
fn some_item(&self) {}
}
impl<T: ?Sized> AmbiguousIfSync<()> for T {}
impl<T: ?Sized + Sync> AmbiguousIfSync<Invalid> for T {}
#[allow(unused)]
trait AmbiguousIfUnpin<A> {
fn some_item(&self) {}
}
+11 -1
View File
@@ -6,13 +6,14 @@ mod support {
}
use support::mpsc;
use tokio_stream::adapters::Chain;
#[tokio::test]
async fn basic_usage() {
let one = stream::iter(vec![1, 2, 3]);
let two = stream::iter(vec![4, 5, 6]);
let mut stream = one.chain(two);
let mut stream = visibility_test(one, two);
assert_eq!(stream.size_hint(), (6, Some(6)));
assert_eq!(stream.next().await, Some(1));
@@ -39,7 +40,16 @@ async fn basic_usage() {
assert_eq!(stream.next().await, None);
}
fn visibility_test<I, S1, S2>(s1: S1, s2: S2) -> Chain<S1, S2>
where
S1: Stream<Item = I>,
S2: Stream<Item = I>,
{
s1.chain(s2)
}
#[tokio::test]
#[cfg_attr(miri, ignore)] // Block on https://github.com/tokio-rs/tokio/issues/6860
async fn pending_first() {
let (tx1, rx1) = mpsc::unbounded_channel_stream();
let (tx2, rx2) = mpsc::unbounded_channel_stream();
+1 -1
View File
@@ -1,7 +1,7 @@
#![cfg(all(feature = "time", feature = "sync", feature = "io-util"))]
use tokio::time::{self, sleep, Duration};
use tokio_stream::{self, StreamExt};
use tokio_stream::StreamExt;
use tokio_test::*;
use futures::stream;
+1 -1
View File
@@ -6,7 +6,7 @@ name = "tokio-test"
# - Create "tokio-test-0.4.x" git tag.
version = "0.4.4"
edition = "2021"
rust-version = "1.63"
rust-version = "1.70"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
+18 -22
View File
@@ -1,25 +1,21 @@
Copyright (c) 2023 Tokio Contributors
MIT License
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
Copyright (c) Tokio Contributors
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+2 -2
View File
@@ -23,13 +23,13 @@ use tokio::sync::mpsc;
use tokio::time::{self, Duration, Instant, Sleep};
use tokio_stream::wrappers::UnboundedReceiverStream;
use futures_core::{ready, Stream};
use futures_core::Stream;
use std::collections::VecDeque;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{self, Poll, Waker};
use std::task::{self, ready, Poll, Waker};
use std::{cmp, io};
/// An I/O object that follows a predefined script.
+1
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![warn(
missing_debug_implementations,
missing_docs,
+3 -4
View File
@@ -36,10 +36,10 @@
use std::collections::VecDeque;
use std::pin::Pin;
use std::task::Poll;
use std::task::{ready, Poll};
use std::time::Duration;
use futures_core::{ready, Stream};
use futures_core::Stream;
use std::future::Future;
use tokio::time::{sleep_until, Instant, Sleep};
@@ -161,8 +161,7 @@ impl<T: Unpin> Drop for StreamMock<T> {
assert!(
undropped_count == 0,
"StreamMock was dropped before all actions were consumed, {} actions were not consumed",
undropped_count
"StreamMock was dropped before all actions were consumed, {undropped_count} actions were not consumed"
);
}
}
+4
View File
@@ -148,6 +148,10 @@ impl<T: Stream> Stream for Spawn<T> {
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.future.as_mut().poll_next(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.future.size_hint()
}
}
impl MockTask {
+2 -2
View File
@@ -34,7 +34,7 @@ async fn read_error() {
match mock.read(&mut buf).await {
Err(error) => {
assert_eq!(error.kind(), io::ErrorKind::Other);
assert_eq!("cruel", format!("{}", error));
assert_eq!("cruel", format!("{error}"));
}
Ok(_) => panic!("error not received"),
}
@@ -87,7 +87,7 @@ async fn write_error() {
match mock.write_all(b"whoa").await {
Err(error) => {
assert_eq!(error.kind(), io::ErrorKind::Other);
assert_eq!("cruel", format!("{}", error));
assert_eq!("cruel", format!("{error}"));
}
Ok(_) => panic!("error not received"),
}
+25
View File
@@ -0,0 +1,25 @@
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio_stream::Stream;
use tokio_test::task;
/// A [`Stream`] that has a stub size hint.
struct SizedStream;
impl Stream for SizedStream {
type Item = ();
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Poll::Pending
}
fn size_hint(&self) -> (usize, Option<usize>) {
(100, Some(200))
}
}
#[test]
fn test_spawn_stream_size_hint() {
let spawn = task::spawn(SizedStream);
assert_eq!(spawn.size_hint(), (100, Some(200)));
}
+65
View File
@@ -1,3 +1,68 @@
# 0.7.13 (December 4th, 2024)
### Fixed
- codec: fix incorrect handling of invalid utf-8 in `LinesCodec::decode_eof` ([#7011])
[#7011]: https://github.com/tokio-rs/tokio/pull/7011
# 0.7.12 (September 5th, 2024)
This release bumps the MSRV to 1.70. ([#6645])
### Added
- sync: Add `run_until_cancelled` to `tokio_util::sync::CancellationToken` ([#6618])
- task: add `AbortOnDropHandle` type ([#6786])
### Changed
- deps: no default features for hashbrown ([#6541])
- time: wake `DelayQueue` when removing last item ([#6752])
- deps: enable the full feature when compiled for the playground ([#6818])
### Documented
- task: fix typo in `TaskTracker` docs ([#6792])
[#6645]: https://github.com/tokio-rs/tokio/pull/6645
[#6541]: https://github.com/tokio-rs/tokio/pull/6541
[#6618]: https://github.com/tokio-rs/tokio/pull/6618
[#6752]: https://github.com/tokio-rs/tokio/pull/6752
[#6786]: https://github.com/tokio-rs/tokio/pull/6786
[#6792]: https://github.com/tokio-rs/tokio/pull/6792
[#6818]: https://github.com/tokio-rs/tokio/pull/6818
# 0.7.11 (May 4th, 2024)
This release updates the MSRV to 1.63. ([#6126])
### Added
- either: implement `Sink` for `Either` ([#6239])
- time: add `DelayQueue::deadline` ([#6163])
- time: add `FutureExt::timeout` ([#6276])
### Changed
- codec: assert compatibility between `LengthDelimitedCodec` options ([#6414])
- codec: make tracing feature optional for codecs ([#6434])
- io: add `T: ?Sized` to `tokio_util::io::poll_read_buf` ([#6441])
- sync: remove `'static` bound on `impl Sink for PollSender` ([#6397])
### Documented
- codec: add examples for `FramedRead` and `FramedWrite` ([#6310])
- codec: document cancel safety of `SinkExt::send` and `StreamExt::next` ([#6417])
[#6126]: https://github.com/tokio-rs/tokio/pull/6126
[#6163]: https://github.com/tokio-rs/tokio/pull/6163
[#6239]: https://github.com/tokio-rs/tokio/pull/6239
[#6276]: https://github.com/tokio-rs/tokio/pull/6276
[#6310]: https://github.com/tokio-rs/tokio/pull/6310
[#6397]: https://github.com/tokio-rs/tokio/pull/6397
[#6414]: https://github.com/tokio-rs/tokio/pull/6414
[#6417]: https://github.com/tokio-rs/tokio/pull/6417
[#6434]: https://github.com/tokio-rs/tokio/pull/6434
[#6441]: https://github.com/tokio-rs/tokio/pull/6441
# 0.7.10 (October 24th, 2023)
### Added
+8 -5
View File
@@ -4,9 +4,9 @@ name = "tokio-util"
# - Remove path dependencies
# - Update CHANGELOG.md.
# - Create "tokio-util-0.7.x" git tag.
version = "0.7.10"
version = "0.7.13"
edition = "2021"
rust-version = "1.63"
rust-version = "1.70"
authors = ["Tokio Contributors <[email protected]>"]
license = "MIT"
repository = "https://github.com/tokio-rs/tokio"
@@ -25,7 +25,7 @@ full = ["codec", "compat", "io-util", "time", "net", "rt"]
net = ["tokio/net"]
compat = ["futures-io",]
codec = ["tracing"]
codec = []
time = ["tokio/time","slab"]
io = []
io-util = ["io", "tokio/rt", "tokio/io-util"]
@@ -42,10 +42,10 @@ futures-io = { version = "0.3.0", optional = true }
futures-util = { version = "0.3.0", optional = true }
pin-project-lite = "0.2.11"
slab = { version = "0.4.4", optional = true } # Backs `DelayQueue`
tracing = { version = "0.1.25", default-features = false, features = ["std"], optional = true }
tracing = { version = "0.1.29", default-features = false, features = ["std"], optional = true }
[target.'cfg(tokio_unstable)'.dependencies]
hashbrown = { version = "0.14.0", optional = true }
hashbrown = { version = "0.14.0", default-features = false, optional = true }
[dev-dependencies]
tokio = { version = "1.0.0", path = "../tokio", features = ["full"] }
@@ -65,3 +65,6 @@ 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"]
[package.metadata.playground]
features = ["full"]
+18 -22
View File
@@ -1,25 +1,21 @@
Copyright (c) 2023 Tokio Contributors
MIT License
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
Copyright (c) Tokio Contributors
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+2 -2
View File
@@ -2,7 +2,7 @@ use crate::codec::decoder::Decoder;
use crate::codec::encoder::Encoder;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::{cmp, fmt, io, str, usize};
use std::{cmp, fmt, io, str};
const DEFAULT_SEEK_DELIMITERS: &[u8] = b",;\n\r";
const DEFAULT_SEQUENCE_WRITER: &[u8] = b",";
@@ -249,7 +249,7 @@ impl fmt::Display for AnyDelimiterCodecError {
AnyDelimiterCodecError::MaxChunkLengthExceeded => {
write!(f, "max chunk length exceeded")
}
AnyDelimiterCodecError::Io(e) => write!(f, "{}", e),
AnyDelimiterCodecError::Io(e) => write!(f, "{e}"),
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ pub trait Encoder<Item> {
/// The type of encoding errors.
///
/// [`FramedWrite`] requires `Encoder`s errors to implement `From<io::Error>`
/// in the interest letting it return `Error`s directly.
/// in the interest of letting it return `Error`s directly.
///
/// [`FramedWrite`]: crate::codec::FramedWrite
type Error: From<io::Error>;
+1 -3
View File
@@ -5,14 +5,12 @@ use futures_core::Stream;
use tokio::io::{AsyncRead, AsyncWrite};
use bytes::BytesMut;
use futures_core::ready;
use futures_sink::Sink;
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;
use std::task::{ready, Context, Poll};
pin_project! {
#[derive(Debug)]
+90 -84
View File
@@ -75,55 +75,23 @@
//!
//! ## Example 1
//!
//! The following will parse a `u16` length field at offset 0, including the
//! frame head in the yielded `BytesMut`.
//!
//! ```
//! # use tokio::io::AsyncRead;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # fn bind_read<T: AsyncRead>(io: T) {
//! LengthDelimitedCodec::builder()
//! .length_field_offset(0) // default value
//! .length_field_type::<u16>()
//! .length_adjustment(0) // default value
//! .num_skip(0) // Do not strip frame header
//! .new_read(io);
//! # }
//! # pub fn main() {}
//! ```
//!
//! The following frame will be decoded as such:
//!
//! ```text
//! INPUT DECODED
//! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+
//! | \x00\x0B | Hello world | --> | \x00\x0B | Hello world |
//! +----------+---------------+ +----------+---------------+
//! ```
//!
//! The value of the length field is 11 (`\x0B`) which represents the length
//! of the payload, `hello world`. By default, [`FramedRead`] assumes that
//! the length field represents the number of bytes that **follows** the
//! length field. Thus, the entire frame has a length of 13: 2 bytes for the
//! frame head + 11 bytes for the payload.
//!
//! ## Example 2
//!
//! The following will parse a `u16` length field at offset 0, omitting the
//! frame head in the yielded `BytesMut`.
//!
//! ```
//! # use tokio::io::AsyncRead;
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # fn bind_read<T: AsyncRead>(io: T) {
//! LengthDelimitedCodec::builder()
//! # #[tokio::main]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x0BHello world";
//! let mut reader = LengthDelimitedCodec::builder()
//! .length_field_offset(0) // default value
//! .length_field_type::<u16>()
//! .length_adjustment(0) // default value
//! // `num_skip` is not needed, the default is to skip
//! .new_read(io);
//! # let res = reader.next().await.unwrap().unwrap().to_vec();
//! # assert_eq!(res, b"Hello world");
//! # }
//! # pub fn main() {}
//! ```
//!
//! The following frame will be decoded as such:
@@ -135,27 +103,32 @@
//! +----------+---------------+ +---------------+
//! ```
//!
//! This is similar to the first example, the only difference is that the
//! frame head is **not** included in the yielded `BytesMut` value.
//! The value of the length field is 11 (`\x0B`) which represents the length
//! of the payload, `hello world`. By default, [`FramedRead`] assumes that
//! the length field represents the number of bytes that **follows** the
//! length field. Thus, the entire frame has a length of 13: 2 bytes for the
//! frame head + 11 bytes for the payload.
//!
//! ## Example 3
//! ## Example 2
//!
//! The following will parse a `u16` length field at offset 0, including the
//! frame head in the yielded `BytesMut`. In this case, the length field
//! **includes** the frame head length.
//! frame head in the yielded `BytesMut`.
//!
//! ```
//! # use tokio::io::AsyncRead;
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # fn bind_read<T: AsyncRead>(io: T) {
//! LengthDelimitedCodec::builder()
//! # #[tokio::main]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x0BHello world";
//! let mut reader = LengthDelimitedCodec::builder()
//! .length_field_offset(0) // default value
//! .length_field_type::<u16>()
//! .length_adjustment(-2) // size of head
//! .num_skip(0)
//! .length_adjustment(2) // Add head size to length
//! .num_skip(0) // Do NOT skip the head
//! .new_read(io);
//! # let res = reader.next().await.unwrap().unwrap().to_vec();
//! # assert_eq!(res, b"\x00\x0BHello world");
//! # }
//! # pub fn main() {}
//! ```
//!
//! The following frame will be decoded as such:
@@ -163,10 +136,46 @@
//! ```text
//! INPUT DECODED
//! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+
//! | \x00\x0D | Hello world | --> | \x00\x0D | Hello world |
//! | \x00\x0B | Hello world | --> | \x00\x0B | Hello world |
//! +----------+---------------+ +----------+---------------+
//! ```
//!
//! This is similar to the first example, the only difference is that the
//! frame head is **included** in the yielded `BytesMut` value. To achieve
//! this, we need to add the header size to the length with `length_adjustment`,
//! and set `num_skip` to `0` to prevent skipping the head.
//!
//! ## Example 3
//!
//! The following will parse a `u16` length field at offset 0, omitting the
//! frame head in the yielded `BytesMut`. In this case, the length field
//! **includes** the frame head length.
//!
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x0DHello world";
//! let mut reader = LengthDelimitedCodec::builder()
//! .length_field_offset(0) // default value
//! .length_field_type::<u16>()
//! .length_adjustment(-2) // size of head
//! .new_read(io);
//! # let res = reader.next().await.unwrap().unwrap().to_vec();
//! # assert_eq!(res, b"Hello world");
//! # }
//! ```
//!
//! The following frame will be decoded as such:
//!
//! ```text
//! INPUT DECODED
//! +-- len ---+--- Payload ---+ +--- Payload ---+
//! | \x00\x0D | Hello world | --> | Hello world |
//! +----------+---------------+ +---------------+
//! ```
//!
//! In most cases, the length field represents the length of the payload
//! only, as shown in the previous examples. However, in some protocols the
//! length field represents the length of the whole frame, including the
@@ -179,17 +188,20 @@
//! frame head, including the frame head in the yielded `BytesMut`.
//!
//! ```
//! # use tokio::io::AsyncRead;
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # fn bind_read<T: AsyncRead>(io: T) {
//! LengthDelimitedCodec::builder()
//! # #[tokio::main]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x00\x0B\xCA\xFEHello world";
//! let mut reader = LengthDelimitedCodec::builder()
//! .length_field_offset(0) // default value
//! .length_field_length(3)
//! .length_adjustment(2) // remaining head
//! .length_adjustment(3 + 2) // len field and remaining head
//! .num_skip(0)
//! .new_read(io);
//! # let res = reader.next().await.unwrap().unwrap().to_vec();
//! # assert_eq!(res, b"\x00\x00\x0B\xCA\xFEHello world");
//! # }
//! # pub fn main() {}
//! ```
//!
//! The following frame will be decoded as such:
@@ -223,17 +235,20 @@
//! included.
//!
//! ```
//! # use tokio::io::AsyncRead;
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # fn bind_read<T: AsyncRead>(io: T) {
//! LengthDelimitedCodec::builder()
//! # #[tokio::main]
//! # async fn main() {
//! # let io: &[u8] = b"\xCA\x00\x0B\xFEHello world";
//! let mut reader = LengthDelimitedCodec::builder()
//! .length_field_offset(1) // length of hdr1
//! .length_field_type::<u16>()
//! .length_adjustment(1) // length of hdr2
//! .num_skip(3) // length of hdr1 + LEN
//! .new_read(io);
//! # let res = reader.next().await.unwrap().unwrap().to_vec();
//! # assert_eq!(res, b"\xFEHello world");
//! # }
//! # pub fn main() {}
//! ```
//!
//! The following frame will be decoded as such:
@@ -269,15 +284,19 @@
//! length.
//!
//! ```
//! # use tokio::io::AsyncRead;
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # fn bind_read<T: AsyncRead>(io: T) {
//! LengthDelimitedCodec::builder()
//! # #[tokio::main]
//! # async fn main() {
//! # let io: &[u8] = b"\xCA\x00\x0F\xFEHello world";
//! let mut reader = LengthDelimitedCodec::builder()
//! .length_field_offset(1) // length of hdr1
//! .length_field_type::<u16>()
//! .length_adjustment(-3) // length of hdr1 + LEN, negative
//! .num_skip(3)
//! .new_read(io);
//! # let res = reader.next().await.unwrap().unwrap().to_vec();
//! # assert_eq!(res, b"\xFEHello world");
//! # }
//! ```
//!
@@ -308,17 +327,20 @@
//! frame head, excluding the 4th byte from the yielded `BytesMut`.
//!
//! ```
//! # use tokio::io::AsyncRead;
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # fn bind_read<T: AsyncRead>(io: T) {
//! LengthDelimitedCodec::builder()
//! # #[tokio::main]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x00\x0B\xFFHello world";
//! let mut reader = LengthDelimitedCodec::builder()
//! .length_field_offset(0) // default value
//! .length_field_length(3)
//! .length_adjustment(0) // default value
//! .num_skip(4) // skip the first 4 bytes
//! .new_read(io);
//! # let res = reader.next().await.unwrap().unwrap().to_vec();
//! # assert_eq!(res, b"Hello world");
//! # }
//! # pub fn main() {}
//! ```
//!
//! The following frame will be decoded as such:
@@ -639,7 +661,6 @@ mod builder {
impl LengthFieldType for u64 {}
#[cfg(any(
target_pointer_width = "8",
target_pointer_width = "16",
target_pointer_width = "32",
target_pointer_width = "64",
@@ -1028,28 +1049,13 @@ impl Builder {
}
fn adjust_max_frame_len(&mut self) {
// This function is basically `std::u64::saturating_add_signed`. Since it
// requires MSRV 1.66, its implementation is copied here.
//
// TODO: use the method from std when MSRV becomes >= 1.66
fn saturating_add_signed(num: u64, rhs: i64) -> u64 {
let (res, overflow) = num.overflowing_add(rhs as u64);
if overflow == (rhs < 0) {
res
} else if overflow {
u64::MAX
} else {
0
}
}
// Calculate the maximum number that can be represented using `length_field_len` bytes.
let max_number = match 1u64.checked_shl((8 * self.length_field_len) as u32) {
Some(shl) => shl - 1,
None => u64::MAX,
};
let max_allowed_len = saturating_add_signed(max_number, self.length_adjustment as i64);
let max_allowed_len = max_number.saturating_add_signed(self.length_adjustment as i64);
if self.max_frame_len as u64 > max_allowed_len {
self.max_frame_len = usize::try_from(max_allowed_len).unwrap_or(usize::MAX);
+3 -3
View File
@@ -2,7 +2,7 @@ use crate::codec::decoder::Decoder;
use crate::codec::encoder::Encoder;
use bytes::{Buf, BufMut, BytesMut};
use std::{cmp, fmt, io, str, usize};
use std::{cmp, fmt, io, str};
/// A simple [`Decoder`] and [`Encoder`] implementation that splits up data into lines.
///
@@ -169,6 +169,7 @@ impl Decoder for LinesCodec {
Ok(match self.decode(buf)? {
Some(frame) => Some(frame),
None => {
self.next_index = 0;
// No terminating newline - return remaining data, if any
if buf.is_empty() || buf == &b"\r"[..] {
None
@@ -176,7 +177,6 @@ impl Decoder for LinesCodec {
let line = buf.split_to(buf.len());
let line = without_carriage_return(&line);
let line = utf8(line)?;
self.next_index = 0;
Some(line.to_string())
}
}
@@ -218,7 +218,7 @@ impl fmt::Display for LinesCodecError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LinesCodecError::MaxLineLengthExceeded => write!(f, "max line length exceeded"),
LinesCodecError::Io(e) => write!(f, "{}", e),
LinesCodecError::Io(e) => write!(f, "{e}"),
}
}
}
+1 -2
View File
@@ -1,10 +1,9 @@
//! Compatibility between the `tokio::io` and `futures-io` versions of the
//! `AsyncRead` and `AsyncWrite` traits.
use futures_core::ready;
use pin_project_lite::pin_project;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
pin_project! {
/// A compatibility layer that allows conversion between the
+1 -2
View File
@@ -1,8 +1,7 @@
use futures_core::ready;
use pin_project_lite::pin_project;
use std::io::{IoSlice, Result};
use std::pin::Pin;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+1 -2
View File
@@ -1,11 +1,10 @@
use futures_core::ready;
use futures_sink::Sink;
use futures_core::stream::Stream;
use pin_project_lite::pin_project;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite};
pin_project! {
+1 -1
View File
@@ -326,7 +326,7 @@ impl<S, B> StreamReader<S, B> {
}
}
impl<S: Sink<T, Error = E>, E, T> Sink<T> for StreamReader<S, E> {
impl<S: Sink<T, Error = E>, B, E, T> Sink<T> for StreamReader<S, B> {
type Error = E;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().inner.poll_ready(cx)
+4
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![allow(clippy::needless_doctest_main)]
#![warn(
missing_debug_implementations,
@@ -25,6 +26,9 @@ mod cfg;
mod loom;
cfg_codec! {
#[macro_use]
mod tracing;
pub mod codec;
}
+46
View File
@@ -241,6 +241,52 @@ impl CancellationToken {
pub fn drop_guard(self) -> DropGuard {
DropGuard { inner: Some(self) }
}
/// Runs a future to completion and returns its result wrapped inside of an `Option`
/// unless the `CancellationToken` is cancelled. In that case the function returns
/// `None` and the future gets dropped.
///
/// # Cancel safety
///
/// This method is only cancel safe if `fut` is cancel safe.
pub async fn run_until_cancelled<F>(&self, fut: F) -> Option<F::Output>
where
F: Future,
{
pin_project! {
/// A Future that is resolved once the corresponding [`CancellationToken`]
/// is cancelled or a given Future gets resolved. It is biased towards the
/// Future completion.
#[must_use = "futures do nothing unless polled"]
struct RunUntilCancelledFuture<'a, F: Future> {
#[pin]
cancellation: WaitForCancellationFuture<'a>,
#[pin]
future: F,
}
}
impl<'a, F: Future> Future for RunUntilCancelledFuture<'a, F> {
type Output = Option<F::Output>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if let Poll::Ready(res) = this.future.poll(cx) {
Poll::Ready(Some(res))
} else if this.cancellation.poll(cx).is_ready() {
Poll::Ready(None)
} else {
Poll::Pending
}
}
}
RunUntilCancelledFuture {
cancellation: self.cancelled(),
future: fut,
}
.await
}
}
// ===== impl WaitForCancellationFuture =====
@@ -206,7 +206,7 @@ fn move_children_to_parent(node: &mut Inner, parent: &mut Inner) {
for child in std::mem::take(&mut node.children) {
{
let mut child_locked = child.inner.lock().unwrap();
child_locked.parent = node.parent.clone();
child_locked.parent.clone_from(&node.parent);
child_locked.parent_idx = parent.children.len();
}
parent.children.push(child);
+2 -2
View File
@@ -1,8 +1,8 @@
use futures_core::{ready, Stream};
use futures_core::Stream;
use std::fmt;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
use tokio::sync::{AcquireError, OwnedSemaphorePermit, Semaphore, TryAcquireError};
use super::ReusableBoxFuture;

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