Compare commits

...
Author SHA1 Message Date
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
Alice Ryhl 9c337ca1a3 chore: prepare Tokio v1.37.0 (#6435) 2024-03-28 17:34:42 +01:00
M.Amin Rayej e542501439 io: document cancel safety of AsyncBufReadExt::fill_buf (#6431) 2024-03-26 20:45:15 +03:30
M.Amin Rayej 4601c84718 stream: add next_many and poll_next_many to StreamMap (#6409) 2024-03-26 18:38:53 +03:30
M.Amin Rayej deff2524c3 util: document cancel safety of SinkExt::send and StreamExt::next (#6417) 2024-03-25 01:53:01 +03:30
Matthieu Le brazidec (r3v2d0g) 4565b81097 sync: add a rwlock() method to owned RwLock guards (#6418) 2024-03-25 00:37:05 +09:00
Ilson Balliego 3ce4720a45 sync: add is_closed, is_empty, and len to mpsc receivers (#6348)
Fixes: #4638
2024-03-24 14:46:02 +01:00
M.Amin Rayej 8342e4b524 util: assert compatibility between LengthDelimitedCodec options (#6414) 2024-03-24 01:12:24 +03:30
Motoyuki Kimura 4c453e9790 readme: add description about benchmarks (#6425) 2024-03-23 18:11:41 +03:30
M.Amin Rayej 1846483f19 sync: expose strong and weak counts of mpsc sender handles (#6405) 2024-03-22 23:25:33 +03:30
Christopher Acosta baad270b98 sync: add Semaphore example for limiting the number of outgoing requests (#6419) 2024-03-22 21:33:28 +03:30
Motoyuki Kimura f9d78fbe92 fs: add set_max_buf_size to tokio::fs::File (#6411) 2024-03-22 17:28:29 +03:30
M.Amin Rayej bb25a06f34 chore: fix dead code warnings (#6423) 2024-03-22 13:44:18 +03:30
M.Amin Rayej d51f16855b runtime: panic if unhandled_panic is enabled when not supported (#6410) 2024-03-20 09:48:09 +01:00
M.Amin Rayej 5baa8d58ec sync: remove stale comment (#6406) 2024-03-17 19:29:10 +03:30
M.Amin Rayej bd51feac47 readme: fix running loom tests guide (#6408) 2024-03-17 14:57:31 +03:30
M.Amin Rayej b2896feb5b io: use Mutex instead of spinlock (#6403) 2024-03-16 12:36:20 +03:30
Alice Ryhl 3d0d0fd2af chore: prepare tokio-test v0.4.4 (#6400) 2024-03-14 22:10:15 +01:00
Alice Ryhl 7cfb100796 chore: prepare tokio-stream v0.1.15 (#6401) 2024-03-14 22:10:05 +01:00
M.Amin Rayej e37bd63854 io: implement try_new and try_with_interest for AsyncFd (#6345) 2024-03-14 22:48:26 +09:00
Vincent Palancher c9e75785c8 sync: remove 'static bound on impl Sink for PollSender (#6397)
In PR #5665, the `'static` bound has been removed on values sent into
`PollSender`. One of this bound was remaining on the `PollSender`
implementation of `Sink`. This patch removes it and adds some tests on
the `Sink` interface for `PollSender`.
2024-03-14 10:23:59 +01:00
kim / Motoyuki Kimura 3141ed6228 sync: update watch channel docs (#6395) 2024-03-13 17:24:19 +01:00
Alice Ryhl ea1cfbdb97 sync: reorder const_new before new_with (#6392) 2024-03-12 14:22:25 +00:00
Alice Ryhl fb2dc97468 readme: update commit message guidelines (#6393) 2024-03-12 14:21:08 +00:00
kim / Motoyuki Kimura a3d2548789 sync: implement Clone for watch::Sender (#6388) 2024-03-12 10:25:43 +01:00
Yotam Ofek b4ab6472de signal: fix typo in argument name (#6389) 2024-03-10 16:24:07 +01:00
M.Amin Rayej 3133af42e1 runtime: make the enter example deterministic (#6351) 2024-03-10 11:37:18 +01:00
Patrick McGleenon 1f924f95f1 chore: fix deprecated circleci image (#6379) 2024-03-06 00:23:38 +09:00
kim / Motoyuki Kimura f6d061919f test: mark Spawn as #[must_use] (#6371) 2024-03-04 16:56:40 +01:00
Lev Kokotov f5ca423bf1 sync: fix missing period in broadcast docs (#6377) 2024-03-04 08:40:03 +00:00
Alice Ryhl e0d33c4a20 tokio: mark 1.36 as an LTS release (#6375) 2024-03-03 20:44:38 +00:00
Alice Ryhl 3125279697 ci: update FreeBSD image to 14 (#6376) 2024-03-03 20:12:58 +00:00
Kevin Reid 5658d7c503 runtime: add doc link from Runtime to #[tokio::main] (#6366) 2024-02-25 22:17:26 +01:00
Patrick McGleenon a2096049ee ci: downgrade to QEMU 7.2 for cross-compile builds (#6361) (#6363) 2024-02-23 12:08:57 +09:00
kim / Motoyuki Kimura 94db07b379 task: add TaskLocalFuture::take_value (#6340) 2024-02-21 11:23:54 +01:00
qj 099ee23b65 docs: fix docsrs build without net feature (#6360) 2024-02-19 11:37:09 +00:00
M.Amin Rayej b32826bc93 runtime: fix leaking registration entries when os registration fails (#6329) 2024-02-15 03:13:08 +03:30
Gil Shoshan 2ce1cee0f9 macros: allow select with only else branch (#6339) 2024-02-13 09:28:16 +01:00
M.Amin Rayej 84e41d4aff io: document cancel safety of AsyncReadExt's primitive read functions (#6337) 2024-02-11 20:45:13 +03:30
Val Lorentz db6929ad62 task: fix documentation links (#6336) 2024-02-11 15:08:01 +01:00
M.Amin Rayej e25d661e08 util: add examples for FramedRead and FramedWrite (#6310) 2024-02-11 02:38:44 +03:30
Patrick McGleenonandRafael Bachmann e392c4ff1e chore: update CI to clippy 1.76 (#6334)
Co-authored-by: Rafael Bachmann <[email protected]>
2024-02-10 10:45:40 +01:00
kim / Motoyuki Kimura 0fbde0e94b sync: add forget_permits method to semaphore (#6331) 2024-02-08 17:40:55 +03:30
Jack Wrenn 10c9eeb6c2 runtime: include task Id in taskdumps (#6328)
Task `Id`s provide a semi-stable identifier for monitoring task
state across task dumps.

Fixes #6313
2024-02-05 22:53:20 +01:00
Alice Ryhl 47a5fe3a12 metrics: fix worker_steal_count test hanging (#6327) 2024-02-05 15:59:04 +00:00
Alice Ryhl fbdf539ac2 sync: make downgrade must_use (#6326) 2024-02-05 08:46:04 +01:00
Alice Ryhl 63caced26f tokio: update CHANGELOG.md (#6324) 2024-02-03 21:57:58 +01:00
erikdesjardins 0b31b2a195 task: implement FromIterator for JoinSet (#6300) 2024-02-02 13:30:49 +01:00
Augusto Hack cb197def68 docs: transition_to_idle doesn't return boolean (#6320) 2024-02-02 13:29:35 +01:00
M.Amin Rayej eaf81ed324 chore: prepare Tokio v1.36.0 (#6312) 2024-02-02 11:13:46 +00:00
M.Amin Rayej 53f9e5a357 ci: make sure dictionary words are sorted and unique (#6316) 2024-01-31 16:11:54 +03:30
M.Amin Rayej 9077762545 net: expose keepalive option on TcpSocket (#6311) 2024-01-30 21:46:37 +03:30
Owen Leung 131e7b4e49 ci: add spellchecking (#6297) 2024-01-29 10:53:43 +01:00
M.Amin Rayej e53b92a993 io: clarify clear_ready docs (#6304) 2024-01-27 20:30:15 +00:00
Sergei Fomin 7536132065 sync: use AtomicBool in broadcast channel future (#6298) 2024-01-27 18:52:55 +00:00
JungChul Shin b6d0c9091d macros: fix trait_method breaking change detection (#6308) 2024-01-26 14:51:44 +01:00
kim / Motoyuki Kimura 4846959e8a runtime: remove obsolete comment (#6303) 2024-01-24 16:22:28 +01:00
M.Amin Rayej ec3038357f net: add UnixSocket (#6290) 2024-01-22 11:35:02 +01:00
Daniel Sedlak f80bbec28f io: simplify check for empty slice (#6293) 2024-01-18 10:59:22 +00:00
M.Amin Rayej eab26a662c net: document that *Fd traits on TcpSocket are unix-only (#6294) 2024-01-18 10:35:46 +01:00
M.Amin Rayej 58edfc61ab ci: verify that tests work with panic=abort (#6283) 2024-01-16 16:10:23 +01:00
Evan Rittenhouse bfd7b08067 time: add FutureExt::timeout (#6276) 2024-01-16 09:51:38 +01:00
M.Amin Rayej 12ce924fb9 task: add JoinSet::try_join_next (#6280) 2024-01-14 10:34:30 +00:00
Jiahao XU e4f9bcb577 process: use pidfd on Linux when available (#6152)
Signed-off-by: Jiahao XU <[email protected]>
2024-01-11 13:58:23 +01:00
zixuan zhao 8463af92af sync: document FIFO behavior of tokio::sync::Mutex (#6279)
Signed-off-by: azuredream <[email protected]>
2024-01-11 11:15:57 +01:00
Taiki Endo 84c5674c60 ci: update clippy version to 1.75 (#6273) 2024-01-07 02:33:37 +09:00
Rustin 3275cfb638 io: make copy cooperative (#6265) 2024-01-06 17:22:26 +01:00
Taiki Endo 9780bf491f ci: update cargo-check-external-types to 0.1.10 (#6274) 2024-01-07 00:53:08 +09:00
Taiki Endo d6ba535ceb ci: update actions/checkout action to v4 (#6272) 2024-01-06 20:30:28 +09:00
Alan Somers e929d0e8b9 tests: update mio-aio to 0.8 (#6269)
This is a test-only dependency.  The main reason for the update is to
avoid transitively depending on a Nix version with a CVE.

mio-aio 0.8.0 has a substantially different API than 0.7.0.  Notably, it
no longer includes any lio_listio functionality.  So to test Tokio's
handling of EVFILT_LIO events we must go low-level and call
libc::lio_listio directly.
2024-01-06 11:14:32 +00:00
Alan Somers 2f730d4d5a ci: update FreeBSD CI environment to 13.2 (#6270)
Because 13.1 is EoL
2024-01-06 11:59:04 +01:00
Alice Ryhl c7e7f203ee chore: typographic improvements (#6262) 2024-01-03 18:01:27 +00:00
Théodore Prévot 7c606ab44a sync: add Sender::{try_,}reserve_many (#6205) 2024-01-02 16:34:56 +00:00
Alice Ryhl 2d2faf6014 rt: improve robustness of wake_in_drop_after_panic test (#6238) 2024-01-02 17:25:51 +01:00
Jesse Schalken c029771247 task: fix typo (#6261) 2024-01-02 12:08:11 +01:00
Owen Leung 7341004535 sync: add {Receiver,UnboundedReceiver}::poll_recv_many (#6236) 2024-01-01 14:26:58 +01:00
Paul Olteanu 02b779e315 sync: add watch::Receiver::mark_unchanged (#6252) 2023-12-30 20:05:37 +00:00
Tymoteusz Wiśniewski 48345d6e48 net: add support for anonymous unix pipes (#6127) 2023-12-30 15:37:47 +00:00
kim / Motoyuki Kimura 581cd41d79 io: make repeat and sink cooperative (#6254) 2023-12-30 15:26:16 +01:00
kim / Motoyuki Kimura 5f7fe8fd0d ci: fix new warnings on 1.75.0 (#6255) 2023-12-29 17:22:54 +01:00
Alice Ryhl 52f28dcb4f benches: fix benchmarking conflicts for real this time (#6246) 2023-12-28 09:52:18 +00:00
Alice Ryhl d51308b035 ci: fix configured clippy msrv (#6244) 2023-12-23 00:28:14 +00:00
Alice Ryhl 7cae89af47 benches: fix benchmarking conflicts (#6243) 2023-12-22 22:43:05 +00:00
Eddy Oyieko 53ad102cf0 util: implement Sink for Either (#6239) 2023-12-22 18:23:04 +01:00
Miccah e7214e3670 io: implement AsyncWrite for Empty (#6235) 2023-12-20 00:05:53 +00:00
Alice Ryhl 433545782e tests: fix name of coop_budget.rs (#6234) 2023-12-19 19:02:02 +00:00
snek bd15bace35 io: add tokio::io::Join (#6220) 2023-12-19 19:51:48 +01:00
Alice Ryhl 410660fd54 Merge 'tokio-1.35.1' into 'master' (#6231) 2023-12-19 18:15:46 +01:00
Alice Ryhl 46ff36386d chore: prepare Tokio v1.35.1 (#6230) 2023-12-19 18:14:34 +01:00
Alice Ryhl 0a1695ebfb Merge 'tokio-1.32.1' into 'tokio-1.35.x' (#6229) 2023-12-19 18:11:16 +01:00
Alice Ryhl c4f0178b74 chore: prepare Tokio v1.32.1 (#6228) 2023-12-19 18:07:05 +01:00
Alice Ryhl 22b3a65934 Merge 'tokio-1.25.3' into 'tokio-1.32.x' (#6227) 2023-12-19 18:00:41 +01:00
Noah Kennedy 0d362339d5 chore: release v1.25.3 (#6223)
# 1.25.3 (December 17thm 2023)

### Fixed
- io: add budgeting to `tokio::runtime::io::registration::async_io` ([#6221])

[#6221]: https://github.com/tokio-rs/tokio/pull/6221
2023-12-19 17:09:44 +01:00
Noah Kennedy ab7313ff6b io: add budgeting to tokio::runtime::io::registration::async_io (#6221)
Fixes #5946.
Fixes #4782.

This change adds budgeting to most of the remaining unbudgeted IO operations which can complete instantly, including datagram send/recv operations and listener socket accepts.

This is particularly significant for scenarios in which resource limits are hit, as it can be common for things like listener tasks to spin when receiving errors and just log them, busy looping worker threads which might otherwise be handling existing connections and closing them.

This can also sometimes lead to complex failure scenarios within datagram systems experiencing resource exhaustion.
2023-12-17 22:34:51 +00:00
oliverandkwfn 4aa7bbff4c chore: typo fixes (#6213)
Co-authored-by: kwfn <[email protected]>
2023-12-11 19:22:55 +00:00
Bryan Baron c06a55088b coop: fix typo in docs for task::unconstrained (#6212) 2023-12-11 17:50:24 +01:00
Alice Ryhl 92a3455c66 chore: prepare Tokio v1.35.0 (#6197) 2023-12-08 23:35:27 +01:00
Alice Ryhl 1968565825 chore: use relaxed load for unsync_load (#6203) 2023-12-08 22:28:40 +00:00
Alice Ryhl c9273f1aee sync: improve safety comments for WakeList (#6200) 2023-12-08 18:57:01 +01:00
Alice Ryhl e05d0f8c2c changelog: fix missing link for 1.8.2 (#6199) 2023-12-08 17:51:46 +00:00
Alice Ryhl debcb2254a Revert "net: add SocketAddr::as_abstract_namespace (#6144)" (#6198)
This reverts commit 2400769b54.
2023-12-08 18:44:32 +01:00
tijsvd 83b7397e44 io: drop the Sized requirements from AsyncReadExt.read_buf (#6169) 2023-12-08 09:51:08 +01:00
NAHO 3991f9f9a4 docs: fix typo in 'tokio/src/sync/broadcast.rs' (#6182) 2023-12-08 09:48:36 +01:00
Alice Ryhl 48c0e6283f chore: use relaxed load for unsync_load on miri (#6179) 2023-12-08 09:48:15 +01:00
Jack Wrenn d561b5850a taskdump: skip notified tasks during taskdumps (#6194)
Fixes #6051
2023-12-08 09:47:46 +01:00
Weijia Jiang 3a4aef17b2 runtime: reduce the lock contention in task spawn (#6001) 2023-12-07 10:45:07 +00:00
Andrew Walbran a0a58d7edd tokio: update nix dependency to 0.27.1 (#6190) 2023-12-04 16:09:58 +01:00
fzyzcjy ed4f766c98 runtime: make Runtime unwind safe (#6189) 2023-12-04 13:07:31 +01:00
zhiqiangxu 3ac4cfb68a runtime: move comment to the right place (#6184) 2023-12-03 11:47:40 +01:00
Kamila Borowska 7232424a81 chore: remove uses of unsafe from maybe_done.rs (#6180) 2023-12-01 12:51:42 +01:00
simlay 4c33ed33f6 net: add Apple watchOS support (#6176) 2023-11-29 21:16:48 +01:00
Alice Ryhl 3468b4b72f runtime: document fairness guarantees and current behavior (#6145) 2023-11-29 12:32:58 +01:00
Hans Krutzer 2400769b54 net: add SocketAddr::as_abstract_namespace (#6144) 2023-11-25 14:44:34 +00:00
aliu a8e8fa6681 time: add DelayQueue::deadline (#6163) 2023-11-23 18:20:26 +01:00
Alice Ryhl 498288cd31 chore: fix docsrs without net feature (#6166) 2023-11-23 15:20:46 +01:00
Hayden Stainsby 7a30504fd4 task: make task span explicit root (#6158)
In Tokio, tasks are optionally instrumented with tracing spans to allow
analysis of the runtime behavior to be performed with tools like
tokio-console.

The span that is created for each task gets currently follows the
default tracing behavior and has a contextual parent attached to it
based on the span that is actual when `tokio::spawn` or similar is
called.

However, in tracing, a span will remain "alive" until all its children
spans are closed. This doesn't match how spawned tasks work. A task may
outlive the context in which is was spawned (and frequently does). This
causes tasks which spawn other - longer living - tasks to appear in
`tokio-console` as having lost their waker when instead they should be
shown as completed (tokio-rs/console#345). It can also cause undesired
behavior for unrelated tracing spans if a subscriber is receiving both
the other spans as well as Tokio's instrumentation.

To fix this mismatch in behavior, the task span has `parent: None` set
on it, making it an explicit root - it has no parent. The same was
already done for all spans representing resources in #6107. This change
is made within the scope of #5792.

Due to a defect in the currently available `tracing-mock` crate, it is
not possible to test this change at a tracing level
(tokio-rs/tracing#2440). Instead, a test for the `console-subscriber`
has been written which shows that this change fixes the defect as
observed in `tokio-console` (tokio-rs/console#490).
2023-11-19 19:21:19 +01:00
Daniel Sedlak 340d4e5238 runtime: fix comment typos (#6143) 2023-11-19 14:01:29 +01:00
Marc-Andre GirouxandDavid Barsky 7b555185ff sync: avoid creating resource spans with curernt parent, use a None parent instead (#6107)
A child span stored on sync primitives can keep the parent span open,
unable to be closed by subscribers due to the sync resource referencing it.

Fixes: #6106

Co-authored-by: David Barsky <[email protected]>
2023-11-14 16:24:21 -05:00
Hayden Stainsby 135d7ca38e taskdump: fix taskdump cargo config example (#6150)
The documentation for the `Handle::dump()` method includes a description
of the Rust flags needed. However, the sample `.cargo/config.toml` file
is incorrect. It gives the Rust flags as:

```
rustflags = ["--cfg tokio_unstable", "--cfg tokio_taskdump"]
```

However, each command line argument needs to be a separate element in
the array:

```
rustflags = ["--cfg", "tokio_unstable", "--cfg", "tokio_taskdump"]
```

This change corrects that line.
2023-11-14 20:17:05 +01:00
Alice Ryhl e6720f985d metrics: fix hang in worker_overflow_count test (#6146)
Closes: #6054
2023-11-14 20:13:56 +01:00
Alice Ryhl d44e995bb0 task: document cancel safety of LocalSet::run_until (#6147)
Closes: #6122
2023-11-14 20:13:43 +01:00
Alice Ryhl 06660ef00a io: flush in AsyncWriteExt examples (#6149)
Closes: #6068
2023-11-14 20:13:00 +01:00
Alice Ryhl 2e5773a6fe runtime: handle missing context on wake (#6148) 2023-11-14 14:01:10 +01:00
331 changed files with 11321 additions and 3563 deletions
-8
View File
@@ -1,8 +0,0 @@
# See https://github.com/rustsec/rustsec/blob/59e1d2ad0b9cbc6892c26de233d4925074b4b97b/cargo-audit/audit.toml.example for example.
[advisories]
ignore = [
# We depend on nix 0.22 only via mio-aio, a dev-dependency.
# https://github.com/tokio-rs/tokio/pull/4255#issuecomment-974786349
"RUSTSEC-2021-0119",
]
+1 -1
View File
@@ -2,7 +2,7 @@ version: 2.1
jobs:
test-arm:
machine:
image: ubuntu-2004:202101-01
image: default
resource_class: arm.medium
environment:
# Change to pin rust version
+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-13-1
image_family: freebsd-14-0
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
-1
View File
@@ -1 +0,0 @@
msrv = "1.56"
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Audit Check
# https://github.com/rustsec/audit-check/issues/2
+152 -54
View File
@@ -13,10 +13,11 @@ 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.65.0
rust_nightly: nightly-2024-05-05
rust_clippy: '1.77'
# When updating this, also update:
# - README.md
# - tokio/README.md
@@ -25,7 +26,7 @@ env:
# - tokio-util/Cargo.toml
# - tokio-test/Cargo.toml
# - tokio-stream/Cargo.toml
rust_min: 1.63.0
rust_min: '1.63'
defaults:
run:
@@ -67,10 +68,11 @@ jobs:
- x86_64-fortanix-unknown-sgx
- check-redox
- wasm32-unknown-unknown
- wasm32-wasi
- wasm32-wasip1
- check-external-types
- check-fuzzing
- check-unstable-mt-counters
- check-spelling
steps:
- run: exit 0
@@ -97,7 +99,7 @@ jobs:
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -129,7 +131,7 @@ jobs:
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -148,6 +150,34 @@ jobs:
cargo nextest run --workspace --all-features
cargo test --doc --workspace --all-features
test-workspace-all-features-panic-abort:
needs: basics
name: test all crates in the workspace with all features and panic=abort
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- windows-latest
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_nightly }}
- name: Install cargo-nextest
uses: taiki-e/install-action@v2
with:
tool: cargo-nextest
- uses: Swatinem/rust-cache@v2
- name: test all --all-features panic=abort
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
@@ -159,7 +189,7 @@ jobs:
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -181,11 +211,10 @@ jobs:
run: cargo hack test --each-feature
working-directory: tests-build
# Check benchmarks. Run of benchmarks is done by bench.yml workflow.
# Check benchmarks.
- name: Check benches
run: cargo check --benches
working-directory: benches
# bench.yml workflow runs benchmarks only on linux.
if: startsWith(matrix.os, 'ubuntu')
test-parking_lot:
@@ -200,7 +229,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -222,7 +251,7 @@ jobs:
name: test tokio instrumentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -247,7 +276,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -286,7 +315,7 @@ jobs:
- os: ubuntu-latest
- os: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -320,7 +349,7 @@ jobs:
include:
- os: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -354,7 +383,7 @@ jobs:
include:
- os: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -382,7 +411,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -403,7 +432,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install llvm
# Required to resolve symbols in sanitizer output
run: sudo apt-get install -y llvm
@@ -425,7 +454,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Check semver
uses: obi1kenobi/cargo-semver-checks-action@v2
with:
@@ -443,7 +472,7 @@ jobs:
- powerpc64-unknown-linux-gnu
- arm-linux-androideabi
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -465,7 +494,7 @@ jobs:
- name: armv7-sony-vita-newlibeabihf
exclude_features: "process,signal,rt-process-signal,full"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@nightly
with:
@@ -493,7 +522,7 @@ jobs:
- target: aarch64-unknown-linux-gnu
rustflags: --cfg tokio_taskdump
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
@@ -508,6 +537,7 @@ jobs:
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: ${{ matrix.target }}
qemu: '7.2'
- uses: Swatinem/rust-cache@v2
- name: Tests run with all features (including parking_lot)
@@ -532,7 +562,7 @@ jobs:
- target: aarch64-unknown-linux-gnu
rustflags: --cfg tokio_taskdump
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
@@ -547,6 +577,7 @@ jobs:
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: ${{ matrix.target }}
qemu: '7.2'
- name: Remove `parking_lot` from `full` feature
run: sed -i '0,/parking_lot/{/parking_lot/d;}' tokio/Cargo.toml
@@ -568,7 +599,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -583,6 +614,7 @@ jobs:
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: i686-unknown-linux-gnu
qemu: '7.2'
- uses: Swatinem/rust-cache@v2
- name: test tokio --all-features
@@ -598,7 +630,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -631,7 +663,7 @@ jobs:
# Try with unstable and taskdump feature flags
- { name: "--unstable --taskdump", rustflags: "--cfg tokio_unstable -Dwarnings --cfg tokio_taskdump" }
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -650,7 +682,7 @@ jobs:
name: minrust
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_min }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -666,7 +698,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -698,7 +730,7 @@ jobs:
name: fmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -718,7 +750,7 @@ jobs:
name: clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_clippy }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -733,7 +765,7 @@ jobs:
name: docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -751,7 +783,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -767,7 +799,7 @@ jobs:
name: Check README
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Verify that both READMEs are identical
run: diff README.md tokio/README.md
@@ -786,7 +818,7 @@ jobs:
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -832,7 +864,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -849,7 +881,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@master
with:
@@ -864,7 +896,7 @@ jobs:
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -877,17 +909,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@v3
- 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
@@ -897,28 +934,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
@@ -931,9 +980,9 @@ 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-05-31
- nightly-2023-10-21
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ matrix.rust }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -942,17 +991,34 @@ jobs:
- name: Install cargo-check-external-types
uses: taiki-e/cache-cargo-install-action@v1
with:
tool: [email protected].7
tool: [email protected].10
- name: check-external-types
run: cargo check-external-types --all-features --config external-types.toml
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
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_nightly }}
uses: dtolnay/rust-toolchain@stable
with:
@@ -966,3 +1032,35 @@ jobs:
- name: Check /tokio-stream/
run: cargo fuzz check --all-features
working-directory: tokio-stream
check-spelling:
name: check-spelling
needs: basics
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-spellcheck
uses: taiki-e/install-action@v2
with:
tool: cargo-spellcheck
- uses: actions/checkout@v4
- name: Make sure dictionary words are sorted and unique
run: |
# `sed` removes the first line (number of words) and
# 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
- name: Run cargo-spellcheck
run: cargo spellcheck --code 1
+5 -5
View File
@@ -29,7 +29,7 @@ jobs:
if: github.repository_owner == 'tokio-rs' && (contains(github.event.pull_request.labels.*.name, 'R-loom-sync') || (github.base_ref == null))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
@@ -45,7 +45,7 @@ jobs:
if: github.repository_owner == 'tokio-rs' && (contains(github.event.pull_request.labels.*.name, 'R-loom-time-driver') || (github.base_ref == null))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
@@ -61,7 +61,7 @@ jobs:
if: github.repository_owner == 'tokio-rs' && (contains(github.event.pull_request.labels.*.name, 'R-loom-current-thread') || (github.base_ref == null))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
@@ -84,7 +84,7 @@ jobs:
- scope: loom_multi_thread::group_c
- scope: loom_multi_thread::group_d
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
@@ -109,7 +109,7 @@ jobs:
- scope: loom_multi_thread_alt::group_c
- scope: loom_multi_thread_alt::group_d
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install cargo-audit
run: cargo install cargo-audit
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
stress-test:
- simple_echo_tcp
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@master
with:
+70 -17
View File
@@ -149,23 +149,31 @@ When updating this, also update:
-->
```
cargo +1.65.0 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
@@ -184,9 +192,11 @@ it, `rustfmt` will update your files locally instead.
You can run loom tests with
```
cd tokio # tokio crate in workspace
LOOM_MAX_PREEMPTIONS=1 RUSTFLAGS="--cfg loom" \
LOOM_MAX_PREEMPTIONS=1 LOOM_MAX_BRANCHES=10000 RUSTFLAGS="--cfg loom -C debug_assertions" \
cargo test --lib --release --features full -- --test-threads=1 --nocapture
```
Additionally, you can also add `--cfg tokio_unstable` to the `RUSTFLAGS` environment variable to
run loom tests that test unstable features.
You can run miri tests with
```
@@ -194,6 +204,24 @@ MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-tag-raw-pointers" \
cargo +nightly miri test --features full --lib
```
### Performing spellcheck on tokio codebase
You can perform spell-check on tokio codebase. For details of how to use the spellcheck tool, feel free to visit
https://github.com/drahnr/cargo-spellcheck
```
# First install the spell-check plugin
cargo install --locked cargo-spellcheck
# Then run the cargo spell check command
cargo spellcheck check
```
if the command rejects a word, you should backtick the rejected word if it's code related. If not, the
rejected word should be put into `spellcheck.dic` file.
Note that when you add a word into the file, you should also update the first line which tells the spellcheck tool
the total number of words included in the file
### Tests
If the change being proposed alters code (as opposed to only documentation for
@@ -233,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;
@@ -327,6 +355,29 @@ example would explicitly use `Timeout::new`. For example:
/// # }
```
### Benchmarks
You can run benchmarks locally for the changes you've made to the tokio codebase.
Tokio currently uses [Criterion](https://github.com/bheisler/criterion.rs) as its benchmarking tool. To run a benchmark
against the changes you have made, for example, you can run;
```bash
cd benches
# Run all benchmarks.
cargo bench
# Run all tests in the `benches/fs.rs` file
cargo bench --bench fs
# Run the `async_read_buf` benchmark in `benches/fs.rs` specifically.
cargo bench async_read_buf
# After running benches, you can check the statistics under `tokio/target/criterion/`
```
You can also refer to Criterion docs for additional options and details.
### Commits
It is a recommended best practice to keep your changes as logically grouped as
@@ -350,14 +401,16 @@ A good commit message should describe what changed and why.
and no more than 72 characters)
* be entirely in lowercase with the exception of proper nouns, acronyms, and
the words that refer to code, like function/variable names
* be prefixed with the name of the sub crate being changed (without the `tokio-`
prefix) and start with an imperative verb. If modifying `tokio` proper,
omit the crate prefix.
* start with an imperative verb
* not have a period at the end
* be prefixed with the name of the module being changed; usually this is the
same as the M-* label on the PR
Examples:
* timer: introduce `Timeout` and deprecate `Deadline`
* export `Encoder`, `Decoder`, `Framed*` from tokio_codec
* time: introduce `Timeout` and deprecate `Deadline`
* codec: export `Encoder`, `Decoder`, `Framed*`
* ci: fix the FreeBSD ci configuration
2. Keep the second line blank.
3. Wrap all other lines at 72 columns (except for long URLs).
@@ -374,7 +427,7 @@ A good commit message should describe what changed and why.
Sample complete commit message:
```txt
subcrate: explain the commit in one line
module: explain the commit in one line
Body of commit message is a few lines of text, explaining things
in more detail, possibly giving some background about the issue
+3
View File
@@ -14,3 +14,6 @@ members = [
"tests-build",
"tests-integration",
]
[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.
+5 -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.34.0", features = ["full"] }
tokio = { version = "1.37.0", features = ["full"] }
```
Then, on your main.rs:
@@ -215,18 +215,18 @@ 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.25.x` - LTS release until March 2024. (MSRV 1.49)
* `1.32.x` - LTS release until September 2024. (MSRV 1.63)
* `1.36.x` - LTS release until March 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
use an LTS release.
To use a fixed minor version, you can specify the version with a tilde. For
example, to specify that you wish to use the newest `1.25.x` patch release, you
example, to specify that you wish to use the newest `1.32.x` patch release, you
can use the following dependency specification:
```text
tokio = { version = "~1.25", features = [...] }
tokio = { version = "~1.32", features = [...] }
```
### Previous LTS releases
@@ -235,6 +235,7 @@ tokio = { version = "~1.25", features = [...] }
* `1.14.x` - LTS release until June 2022.
* `1.18.x` - LTS release until June 2023.
* `1.20.x` - LTS release until September 2023.
* `1.25.x` - LTS release until March 2024.
## License
+11
View File
@@ -12,6 +12,7 @@ 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"] }
@@ -25,6 +26,11 @@ name = "spawn"
path = "spawn.rs"
harness = false
[[bench]]
name = "sync_broadcast"
path = "sync_broadcast.rs"
harness = false
[[bench]]
name = "sync_mpsc"
path = "sync_mpsc.rs"
@@ -84,3 +90,8 @@ harness = false
name = "time_now"
path = "time_now.rs"
harness = false
[[bench]]
name = "time_timeout"
path = "time_timeout.rs"
harness = false
+3 -3
View File
@@ -29,7 +29,7 @@ const WRITE_SERVICE_PERIOD: Duration = Duration::from_millis(20);
// because another writer claimed the buffer space
const PROBABILITY_FLUSH_WAIT: f64 = 0.1;
/// A slow writer that aims to simulate HDD behaviour under heavy load.
/// A slow writer that aims to simulate HDD behavior under heavy load.
///
/// There is a limited buffer, which is fully drained on the next write after
/// a time limit is reached. Flush waits for the time limit to be reached
@@ -64,7 +64,7 @@ impl SlowHddWriter {
) -> std::task::Poll<Result<(), std::io::Error>> {
// If we hit a service interval, the buffer can be cleared
let res = self.service_intervals.poll_tick(cx).map(|_| Ok(()));
if let Poll::Ready(_) = res {
if res.is_ready() {
self.buffer_used = 0;
}
res
@@ -123,7 +123,7 @@ impl AsyncWrite for SlowHddWriter {
cx: &mut std::task::Context<'_>,
bufs: &[std::io::IoSlice<'_>],
) -> std::task::Poll<Result<usize, std::io::Error>> {
let writeable = bufs.into_iter().fold(0, |acc, buf| acc + buf.len());
let writeable = bufs.iter().fold(0, |acc, buf| acc + buf.len());
self.write_bytes(cx, writeable)
}
+8 -8
View File
@@ -8,7 +8,7 @@ use criterion::{criterion_group, criterion_main, Criterion};
const NUM_SPAWN: usize = 1_000;
fn spawn_many_local(c: &mut Criterion) {
fn rt_curr_spawn_many_local(c: &mut Criterion) {
let rt = rt();
let mut handles = Vec::with_capacity(NUM_SPAWN);
@@ -27,7 +27,7 @@ fn spawn_many_local(c: &mut Criterion) {
});
}
fn spawn_many_remote_idle(c: &mut Criterion) {
fn rt_curr_spawn_many_remote_idle(c: &mut Criterion) {
let rt = rt();
let rt_handle = rt.handle();
let mut handles = Vec::with_capacity(NUM_SPAWN);
@@ -47,7 +47,7 @@ fn spawn_many_remote_idle(c: &mut Criterion) {
});
}
fn spawn_many_remote_busy(c: &mut Criterion) {
fn rt_curr_spawn_many_remote_busy(c: &mut Criterion) {
let rt = rt();
let rt_handle = rt.handle();
let mut handles = Vec::with_capacity(NUM_SPAWN);
@@ -80,10 +80,10 @@ fn rt() -> Runtime {
}
criterion_group!(
scheduler,
spawn_many_local,
spawn_many_remote_idle,
spawn_many_remote_busy
rt_curr_scheduler,
rt_curr_spawn_many_local,
rt_curr_spawn_many_remote_idle,
rt_curr_spawn_many_remote_busy
);
criterion_main!(scheduler);
criterion_main!(rt_curr_scheduler);
+18 -18
View File
@@ -16,7 +16,7 @@ const NUM_WORKERS: usize = 4;
const NUM_SPAWN: usize = 10_000;
const STALL_DUR: Duration = Duration::from_micros(10);
fn spawn_many_local(c: &mut Criterion) {
fn rt_multi_spawn_many_local(c: &mut Criterion) {
let rt = rt();
let (tx, rx) = mpsc::sync_channel(1000);
@@ -38,13 +38,13 @@ fn spawn_many_local(c: &mut Criterion) {
});
}
let _ = rx.recv().unwrap();
rx.recv().unwrap();
});
})
});
}
fn spawn_many_remote_idle(c: &mut Criterion) {
fn rt_multi_spawn_many_remote_idle(c: &mut Criterion) {
let rt = rt();
let mut handles = Vec::with_capacity(NUM_SPAWN);
@@ -66,7 +66,7 @@ fn spawn_many_remote_idle(c: &mut Criterion) {
// The runtime is busy with tasks that consume CPU time and yield. Yielding is a
// lower notification priority than spawning / regular notification.
fn spawn_many_remote_busy1(c: &mut Criterion) {
fn rt_multi_spawn_many_remote_busy1(c: &mut Criterion) {
let rt = rt();
let rt_handle = rt.handle();
let mut handles = Vec::with_capacity(NUM_SPAWN);
@@ -102,7 +102,7 @@ fn spawn_many_remote_busy1(c: &mut Criterion) {
// The runtime is busy with tasks that consume CPU time and spawn new high-CPU
// tasks. Spawning goes via a higher notification priority than yielding.
fn spawn_many_remote_busy2(c: &mut Criterion) {
fn rt_multi_spawn_many_remote_busy2(c: &mut Criterion) {
const NUM_SPAWN: usize = 1_000;
let rt = rt();
@@ -143,7 +143,7 @@ fn spawn_many_remote_busy2(c: &mut Criterion) {
flag.store(false, Relaxed);
}
fn yield_many(c: &mut Criterion) {
fn rt_multi_yield_many(c: &mut Criterion) {
const NUM_YIELD: usize = 1_000;
const TASKS: usize = 200;
@@ -165,13 +165,13 @@ fn yield_many(c: &mut Criterion) {
}
for _ in 0..TASKS {
let _ = rx.recv().unwrap();
rx.recv().unwrap();
}
})
});
}
fn ping_pong(c: &mut Criterion) {
fn rt_multi_ping_pong(c: &mut Criterion) {
const NUM_PINGS: usize = 1_000;
let rt = rt();
@@ -216,7 +216,7 @@ fn ping_pong(c: &mut Criterion) {
});
}
fn chained_spawn(c: &mut Criterion) {
fn rt_multi_chained_spawn(c: &mut Criterion) {
const ITER: usize = 1_000;
fn iter(done_tx: mpsc::SyncSender<()>, n: usize) {
@@ -263,14 +263,14 @@ fn stall() {
}
criterion_group!(
scheduler,
spawn_many_local,
spawn_many_remote_idle,
spawn_many_remote_busy1,
spawn_many_remote_busy2,
ping_pong,
yield_many,
chained_spawn,
rt_multi_scheduler,
rt_multi_spawn_many_local,
rt_multi_spawn_many_remote_idle,
rt_multi_spawn_many_remote_busy1,
rt_multi_spawn_many_remote_busy2,
rt_multi_ping_pong,
rt_multi_yield_many,
rt_multi_chained_spawn,
);
criterion_main!(scheduler);
criterion_main!(rt_multi_scheduler);
+82
View File
@@ -0,0 +1,82 @@
use rand::{Rng, RngCore, SeedableRng};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use tokio::sync::{broadcast, Notify};
use criterion::measurement::WallTime;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkGroup, Criterion};
fn rt() -> tokio::runtime::Runtime {
tokio::runtime::Builder::new_multi_thread()
.worker_threads(6)
.build()
.unwrap()
}
fn do_work(rng: &mut impl RngCore) -> u32 {
use std::fmt::Write;
let mut message = String::new();
for i in 1..=10 {
let _ = write!(&mut message, " {i}={}", rng.gen::<f64>());
}
message
.as_bytes()
.iter()
.map(|&c| c as u32)
.fold(0, u32::wrapping_add)
}
fn contention_impl<const N_TASKS: usize>(g: &mut BenchmarkGroup<WallTime>) {
let rt = rt();
let (tx, _rx) = broadcast::channel::<usize>(1000);
let wg = Arc::new((AtomicUsize::new(0), Notify::new()));
for n in 0..N_TASKS {
let wg = wg.clone();
let mut rx = tx.subscribe();
let mut rng = rand::rngs::StdRng::seed_from_u64(n as u64);
rt.spawn(async move {
while (rx.recv().await).is_ok() {
let r = do_work(&mut rng);
let _ = black_box(r);
if wg.0.fetch_sub(1, Ordering::Relaxed) == 1 {
wg.1.notify_one();
}
}
});
}
const N_ITERS: usize = 100;
g.bench_function(N_TASKS.to_string(), |b| {
b.iter(|| {
rt.block_on({
let wg = wg.clone();
let tx = tx.clone();
async move {
for i in 0..N_ITERS {
assert_eq!(wg.0.fetch_add(N_TASKS, Ordering::Relaxed), 0);
tx.send(i).unwrap();
while wg.0.load(Ordering::Relaxed) > 0 {
wg.1.notified().await;
}
}
}
})
})
});
}
fn bench_contention(c: &mut Criterion) {
let mut group = c.benchmark_group("contention");
contention_impl::<10>(&mut group);
contention_impl::<100>(&mut group);
contention_impl::<500>(&mut group);
contention_impl::<1000>(&mut group);
group.finish();
}
criterion_group!(contention, bench_contention);
criterion_main!(contention);
+2 -2
View File
@@ -4,7 +4,7 @@ use criterion::measurement::WallTime;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkGroup, Criterion};
#[derive(Debug, Copy, Clone)]
struct Medium([usize; 64]);
struct Medium(#[allow(dead_code)] [usize; 64]);
impl Default for Medium {
fn default() -> Self {
Medium([0; 64])
@@ -12,7 +12,7 @@ impl Default for Medium {
}
#[derive(Debug, Copy, Clone)]
struct Large([Medium; 64]);
struct Large(#[allow(dead_code)] [Medium; 64]);
impl Default for Large {
fn default() -> Self {
Large([Medium::default(); 64])
+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);
+1 -1
View File
@@ -23,7 +23,7 @@ fn main() {
// Without the `HandleExt.wrap()` there would be a panic because there is
// no timer running, since it would be referencing runtime r1.
let _ = rt1.block_on(rt2.wrap(async move {
rt1.block_on(rt2.wrap(async move {
let listener = TcpListener::bind("0.0.0.0:0").await.unwrap();
println!("addr: {:?}", listener.local_addr());
tx.send(()).unwrap();
+3 -2
View File
@@ -47,9 +47,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// capture a dump, and print each trace
println!("{:-<80}", "");
if let Ok(dump) = timeout(Duration::from_secs(2), handle.dump()).await {
for (i, task) in dump.tasks().iter().enumerate() {
for task in dump.tasks().iter() {
let id = task.id();
let trace = task.trace();
println!("TASK {i}:");
println!("TASK {id}:");
println!("{trace}\n");
}
} else {
+2 -2
View File
@@ -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 {
+285
View File
@@ -0,0 +1,285 @@
285
&
+
<
=
>
\
~
0o777
0s
0xA
0xD
100ms
10ms
~12
±1m
±1ms
1ms
1s
250ms
2x
~4
443
450ms
50ms
8MB
adaptor
adaptors
Adaptors
AIO
ambiant
amongst
api
APIs
async
atomics
awaitable
backend
backpressure
backtrace
backtraces
backtracing
binded
bitfield
bitfields
Blockingly
boolean
broadcasted
cancelled
cancelling
Cancelling
CLI
cloneable
codebase
codec
codecs
combinator
combinators
config
Config
connectionless
coroutines
cpu
cpus
Customizable
datagram
Datagram
datagrams
deallocate
deallocated
Deallocates
decrementing
dequeued
deregister
deregistered
deregistering
deregisters
Deregisters
deregistration
descriptor's
destructor
destructors
destructure
Destructures
Dev
dns
DNS
DoS
dwOpenMode
endian
enqueue
enqueued
EntryInner
enum
eof
Erlang's
errored
EWMA
expirations
fcntl
fd's
FIFOs
filename
filesystem
filesystems
fn
fns
FreeBSD
frontend
fs
functionalities
getters
GID
goroutines
Growable
gzip
hashmaps
HashMaps
hashsets
ie
Illumos
impl
implementers
implementor
implementors
incrementing
interoperate
invariants
Invariants
io
IOCP
iOS
IOs
io_uring
IP
IPv4
IPv6
iteratively
Kotlin's
latencies
Lauck
libc
lifecycle
lifo
lookups
macOS
MacOS
Marsaglia's
metadata
mio
Mio
mio's
misconfigured
mock's
mpmc
mpsc
multi
Multi
multicast
Multithreaded
mut
mutex
Mutex
Nagle
nonblocking
nondecreasing
noop
ntasks
ok
oneshot
ORed
os
overweighing
parker
parsers
peekable
PGID
PID
plaintext
poller
POSIX
proxied
qos
RAII
reallocations
recv's
refactors
refcount
refcounting
repo
repr
representable
reqwest
reregistering
resize
resized
RMW
runtime
runtime's
runtimes
rwlock
rx
scalability
scheduler's
semver
setpgid
sharded
signalled
signalling
SmallCrush
Solaris
spawner
Splitter
spmc
spsc
src
stabilised
startup
stateful
stderr
stdin
stdout
stealable
stealer
stealers
struct
structs
subfield
suboptimal
subprocess
superset
symlink
symlinks
sys
syscall
syscalls
tcp
TCP
TestU01
threadpool
timestamp
timestamps
TLS
TOCTOU
TODO
tokio
Tokio
tokio's
Tokio's
tuple
Tuple
tx
udp
UDP
UID
unhandled
unix
unlink
unpark
Unpark
unparked
unparking
unparks
Unparks
unreceived
unsafety
Unsets
unsynchronized
untrusted
usecases
Valgrind
Varghese
vec
versa
versioned
versioning
vtable
waker
wakers
Wakers
wakeup
wakeups
workstealing
+13
View File
@@ -0,0 +1,13 @@
dev_comments = false
skip_readme = false
[Hunspell]
lang = "en_US"
search_dirs = ["."]
extra_dictionaries = ["spellcheck.dic"]
skip_os_lookups = true
use_builtin = true
[Hunspell.quirks]
allow_concatenation = true
+1 -1
View File
@@ -42,7 +42,7 @@ fn main() {
.write_all(one_mega_random_bytes.as_slice())
.await
.unwrap();
stream.read(&mut buff).await.unwrap();
let _ = stream.read(&mut buff).await.unwrap();
}
tx.send(()).unwrap();
});
+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"
@@ -45,4 +45,24 @@ async fn test_crate_not_path_invalid() {}
#[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() {}
@@ -76,20 +76,40 @@ error: Failed to parse value of `crate` as path: "456"
41 | #[tokio::test(crate = "456")]
| ^^^^^
error: second test attribute is supplied
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> $DIR/macros_invalid_input.rs:45:1
|
45 | #[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
--> $DIR/macros_invalid_input.rs:49:1
|
45 | #[test]
| ^^^^^^^
49 | #[::core::prelude::v1::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> $DIR/macros_invalid_input.rs:53:1
|
note: the lint level is defined here
--> $DIR/macros_invalid_input.rs:1:9
53 | #[core::prelude::rust_2015::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> $DIR/macros_invalid_input.rs:57:1
|
1 | #![deny(duplicate_macro_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
57 | #[::std::prelude::rust_2018::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> $DIR/macros_invalid_input.rs:61:1
|
61 | #[std::prelude::rust_2021::test]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: second test attribute is supplied, consider removing or changing the order of your test attributes
--> $DIR/macros_invalid_input.rs:64:1
|
64 | #[tokio::test]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `tokio::test` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -1,24 +1,36 @@
error[E0308]: mismatched types
--> tests/fail/macros_type_mismatch.rs:5:5
|
4 | async fn missing_semicolon_or_return_type() {
| - help: a return type might be missing here: `-> _`
5 | Ok(())
| ^^^^^^ expected `()`, found `Result<(), _>`
|
= note: expected unit type `()`
found enum `Result<(), _>`
help: a return type might be missing here
|
4 | async fn missing_semicolon_or_return_type() -> _ {
| ++++
help: consider using `Result::expect` to unwrap the `Result<(), _>` value, panicking if the value is a `Result::Err`
|
5 | Ok(()).expect("REASON")
| +++++++++++++++++
error[E0308]: mismatched types
--> tests/fail/macros_type_mismatch.rs:10:5
|
9 | async fn missing_return_type() {
| - help: a return type might be missing here: `-> _`
10 | return Ok(());
| ^^^^^^^^^^^^^^ expected `()`, found `Result<(), _>`
|
= note: expected unit type `()`
found enum `Result<(), _>`
help: a return type might be missing here
|
9 | async fn missing_return_type() -> _ {
| ++++
help: consider using `Result::expect` to unwrap the `Result<(), _>` value, panicking if the value is a `Result::Err`
|
10 | return Ok(());.expect("REASON")
| +++++++++++++++++
error[E0308]: mismatched types
--> tests/fail/macros_type_mismatch.rs:23:5
@@ -41,7 +53,7 @@ error[E0308]: mismatched types
--> tests/fail/macros_type_mismatch.rs:32:5
|
30 | async fn issue_4635() {
| - help: try adding a return type: `-> i32`
| - help: try adding a return type: `-> i32`
31 | return 1;
32 | ;
| ^ expected `()`, found integer
+1
View File
@@ -39,6 +39,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",
+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 {
+6
View File
@@ -1,3 +1,9 @@
# 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
+1 -1
View File
@@ -4,7 +4,7 @@ name = "tokio-macros"
# - Remove path dependencies
# - Update CHANGELOG.md.
# - Create "tokio-macros-1.x.y" git tag.
version = "2.2.0"
version = "2.3.0"
edition = "2021"
rust-version = "1.63"
authors = ["Tokio Contributors <[email protected]>"]
+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
+38 -9
View File
@@ -360,7 +360,7 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
rt = quote_spanned! {last_stmt_start_span=> #rt.start_paused(#v) };
}
let header = if is_test {
let generated_attrs = if is_test {
quote! {
#[::core::prelude::v1::test]
}
@@ -410,7 +410,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 +418,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 +442,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 +479,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 +521,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);
@@ -507,12 +533,15 @@ impl ItemFn {
// Inner attributes require extra care, since they're not supported on
// blocks (which is what we're expanded into) we instead lift them
// outside of the function. This matches the behaviour of `syn`.
// outside of the function. This matches the behavior of `syn`.
for mut attr in self.inner_attrs {
attr.style = syn::AttrStyle::Outer;
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);
+1 -2
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![allow(clippy::needless_doctest_main)]
#![warn(
missing_debug_implementations,
@@ -202,7 +203,6 @@ use proc_macro::TokenStream;
/// }
/// ```
#[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 +267,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()
}
+16
View File
@@ -1,3 +1,19 @@
# 0.1.15 (March 14th, 2024)
This release bumps the MSRV of tokio-stream to 1.63.
- docs: fix typo in argument name ([#6389])
- docs: fix typo in peekable docs ([#6130])
- docs: link to latest version of tokio-util docs ([#5694])
- docs: typographic improvements ([#6262])
- stream: add `StreamExt::peekable` ([#6095])
[#5694]: https://github.com/tokio-rs/tokio/pull/5694
[#6095]: https://github.com/tokio-rs/tokio/pull/6095
[#6130]: https://github.com/tokio-rs/tokio/pull/6130
[#6262]: https://github.com/tokio-rs/tokio/pull/6262
[#6389]: https://github.com/tokio-rs/tokio/pull/6389
# 0.1.14 (April 26th, 2023)
This bugfix release bumps the minimum version of Tokio to 1.15, which is
+1 -1
View File
@@ -4,7 +4,7 @@ name = "tokio-stream"
# - Remove path dependencies
# - Update CHANGELOG.md.
# - Create "tokio-stream-0.1.x" git tag.
version = "0.1.14"
version = "0.1.15"
edition = "2021"
rust-version = "1.63"
authors = ["Tokio Contributors <[email protected]>"]
+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.
+5 -1
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![allow(
clippy::cognitive_complexity,
clippy::large_enum_variant,
@@ -54,7 +55,7 @@
//!
//! [async-stream]: https://docs.rs/async-stream
//!
//! # Conversion to and from AsyncRead/AsyncWrite
//! # Conversion to and from `AsyncRead`/`AsyncWrite`
//!
//! It is often desirable to convert a `Stream` into an [`AsyncRead`],
//! especially when dealing with plaintext formats streamed over the network.
@@ -73,6 +74,9 @@
#[macro_use]
mod macros;
mod poll_fn;
pub(crate) use poll_fn::poll_fn;
pub mod wrappers;
mod stream_ext;
+35
View File
@@ -0,0 +1,35 @@
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)
}
}
+116 -12
View File
@@ -1,4 +1,4 @@
use crate::Stream;
use crate::{poll_fn, Stream};
use std::borrow::Borrow;
use std::hash::Hash;
@@ -209,7 +209,7 @@ pub struct StreamMap<K, V> {
impl<K, V> StreamMap<K, V> {
/// An iterator visiting all key-value pairs in arbitrary order.
///
/// The iterator element type is &'a (K, V).
/// The iterator element type is `&'a (K, V)`.
///
/// # Examples
///
@@ -232,7 +232,7 @@ impl<K, V> StreamMap<K, V> {
/// An iterator visiting all key-value pairs mutably in arbitrary order.
///
/// The iterator element type is &'a mut (K, V).
/// The iterator element type is `&'a mut (K, V)`.
///
/// # Examples
///
@@ -289,7 +289,7 @@ impl<K, V> StreamMap<K, V> {
/// Returns an iterator visiting all keys in arbitrary order.
///
/// The iterator element type is &'a K.
/// The iterator element type is `&'a K`.
///
/// # Examples
///
@@ -312,7 +312,7 @@ impl<K, V> StreamMap<K, V> {
/// An iterator visiting all values in arbitrary order.
///
/// The iterator element type is &'a V.
/// The iterator element type is `&'a V`.
///
/// # Examples
///
@@ -335,7 +335,7 @@ impl<K, V> StreamMap<K, V> {
/// An iterator visiting all values mutably in arbitrary order.
///
/// The iterator element type is &'a mut V.
/// The iterator element type is `&'a mut V`.
///
/// # Examples
///
@@ -467,10 +467,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 +496,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 {
@@ -561,6 +561,110 @@ impl<K, V> Default for StreamMap<K, V> {
}
}
impl<K, V> StreamMap<K, V>
where
K: Clone + Unpin,
V: Stream + Unpin,
{
/// Receives multiple items on this [`StreamMap`], extending the provided `buffer`.
///
/// This method returns the number of items that is appended to the `buffer`.
///
/// Note that this method does not guarantee that exactly `limit` items
/// are received. Rather, if at least one item is available, it returns
/// as many items as it can up to the given limit. This method returns
/// zero only if the `StreamMap` is empty (or if `limit` is zero).
///
/// # Cancel safety
///
/// This method is cancel safe. If `next_many` is used as the event in a
/// [`tokio::select!`](tokio::select) statement and some other branch
/// completes first, it is guaranteed that no items were received on any of
/// the underlying streams.
pub async fn next_many(&mut self, buffer: &mut Vec<(K, V::Item)>, limit: usize) -> usize {
poll_fn(|cx| self.poll_next_many(cx, buffer, limit)).await
}
/// Polls to receive multiple items on this `StreamMap`, extending the provided `buffer`.
///
/// This method returns:
/// * `Poll::Pending` if no items are available but the `StreamMap` is not empty.
/// * `Poll::Ready(count)` where `count` is the number of items successfully received and
/// stored in `buffer`. This can be less than, or equal to, `limit`.
/// * `Poll::Ready(0)` if `limit` is set to zero or when the `StreamMap` is empty.
///
/// Note that this method does not guarantee that exactly `limit` items
/// are received. Rather, if at least one item is available, it returns
/// as many items as it can up to the given limit. This method returns
/// zero only if the `StreamMap` is empty (or if `limit` is zero).
pub fn poll_next_many(
&mut self,
cx: &mut Context<'_>,
buffer: &mut Vec<(K, V::Item)>,
limit: usize,
) -> Poll<usize> {
if limit == 0 || self.entries.is_empty() {
return Poll::Ready(0);
}
let mut added = 0;
let start = self::rand::thread_rng_n(self.entries.len() as u32) as usize;
let mut idx = start;
while added < limit {
// Indicates whether at least one stream returned a value when polled or not
let mut should_loop = false;
for _ in 0..self.entries.len() {
let (_, stream) = &mut self.entries[idx];
match Pin::new(stream).poll_next(cx) {
Poll::Ready(Some(val)) => {
added += 1;
let key = self.entries[idx].0.clone();
buffer.push((key, val));
should_loop = true;
idx = idx.wrapping_add(1) % self.entries.len();
}
Poll::Ready(None) => {
// Remove the entry
self.entries.swap_remove(idx);
// Check if this was the last entry, if so the cursor needs
// to wrap
if idx == self.entries.len() {
idx = 0;
} else if idx < start && start <= self.entries.len() {
// The stream being swapped into the current index has
// already been polled, so skip it.
idx = idx.wrapping_add(1) % self.entries.len();
}
}
Poll::Pending => {
idx = idx.wrapping_add(1) % self.entries.len();
}
}
}
if !should_loop {
break;
}
}
if added > 0 {
Poll::Ready(added)
} else if self.entries.is_empty() {
Poll::Ready(0)
} else {
Poll::Pending
}
}
}
impl<K, V> Stream for StreamMap<K, V>
where
K: Clone + Unpin,
@@ -658,9 +762,9 @@ mod rand {
/// Fast random number generate
///
/// Implement xorshift64+: 2 32-bit xorshift sequences added together.
/// Implement `xorshift64+`: 2 32-bit `xorshift` sequences added together.
/// Shift triplet `[17,7,16]` was calculated as indicated in Marsaglia's
/// Xorshift paper: <https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf>
/// `Xorshift` paper: <https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf>
/// This generator passes the SmallCrush suite, part of TestU01 framework:
/// <http://simul.iro.umontreal.ca/testu01/tu01.html>
#[derive(Debug)]
+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
View File
@@ -30,7 +30,6 @@ impl<R> LinesStream<R> {
}
/// Obtain a pinned reference to the inner `Lines<R>`.
#[allow(clippy::wrong_self_convention)] // https://github.com/rust-lang/rust-clippy/issues/4546
pub fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Lines<R>> {
self.project().inner
}
+2 -2
View File
@@ -15,8 +15,8 @@ pub struct SignalStream {
impl SignalStream {
/// Create a new `SignalStream`.
pub fn new(interval: Signal) -> Self {
Self { inner: interval }
pub fn new(signal: Signal) -> Self {
Self { inner: signal }
}
/// Get back the inner `Signal`.
-1
View File
@@ -30,7 +30,6 @@ impl<R> SplitStream<R> {
}
/// Obtain a pinned reference to the inner `Split<R>`.
#[allow(clippy::wrong_self_convention)] // https://github.com/rust-lang/rust-clippy/issues/4546
pub fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Split<R>> {
self.project().inner
}
+1 -1
View File
@@ -10,7 +10,7 @@ use tokio::sync::watch::error::RecvError;
/// A wrapper around [`tokio::sync::watch::Receiver`] that implements [`Stream`].
///
/// This stream will start by yielding the current value when the WatchStream is polled,
/// This stream will start by yielding the current value when the `WatchStream` is polled,
/// regardless of whether it was the initial value or sent afterwards,
/// unless you use [`WatchStream<T>::from_changes`].
///
+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) {}
}
+1
View File
@@ -1,5 +1,6 @@
#![warn(rust_2018_idioms)]
#![cfg(all(feature = "time", not(target_os = "wasi")))] // Wasi does not support panic recovery
#![cfg(panic = "unwind")]
use parking_lot::{const_mutex, Mutex};
use std::error::Error;
+235 -2
View File
@@ -1,14 +1,17 @@
use futures::stream::iter;
use tokio_stream::{self as stream, pending, Stream, StreamExt, StreamMap};
use tokio_test::{assert_ok, assert_pending, assert_ready, task};
use std::future::{poll_fn, Future};
use std::pin::{pin, Pin};
use std::task::Poll;
mod support {
pub(crate) mod mpsc;
}
use support::mpsc;
use std::pin::Pin;
macro_rules! assert_ready_some {
($($t:tt)*) => {
match assert_ready!($($t)*) {
@@ -328,3 +331,233 @@ fn one_ready_many_none() {
fn pin_box<T: Stream<Item = U> + 'static, U>(s: T) -> Pin<Box<dyn Stream<Item = U>>> {
Box::pin(s)
}
type UsizeStream = Pin<Box<dyn Stream<Item = usize> + Send>>;
#[tokio::test]
async fn poll_next_many_zero() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(pending()) as UsizeStream);
let n = poll_fn(|cx| stream_map.poll_next_many(cx, &mut vec![], 0)).await;
assert_eq!(n, 0);
}
#[tokio::test]
async fn poll_next_many_empty() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
let n = poll_fn(|cx| stream_map.poll_next_many(cx, &mut vec![], 1)).await;
assert_eq!(n, 0);
}
#[tokio::test]
async fn poll_next_many_pending() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(pending()) as UsizeStream);
let mut is_pending = false;
poll_fn(|cx| {
let poll = stream_map.poll_next_many(cx, &mut vec![], 1);
is_pending = poll.is_pending();
Poll::Ready(())
})
.await;
assert!(is_pending);
}
#[tokio::test]
async fn poll_next_many_not_enough() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(iter([0usize].into_iter())) as UsizeStream);
stream_map.insert(1, Box::pin(iter([1usize].into_iter())) as UsizeStream);
let mut buffer = vec![];
let n = poll_fn(|cx| stream_map.poll_next_many(cx, &mut buffer, 3)).await;
assert_eq!(n, 2);
assert_eq!(buffer.len(), 2);
assert!(buffer.contains(&(0, 0)));
assert!(buffer.contains(&(1, 1)));
}
#[tokio::test]
async fn poll_next_many_enough() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(iter([0usize].into_iter())) as UsizeStream);
stream_map.insert(1, Box::pin(iter([1usize].into_iter())) as UsizeStream);
let mut buffer = vec![];
let n = poll_fn(|cx| stream_map.poll_next_many(cx, &mut buffer, 2)).await;
assert_eq!(n, 2);
assert_eq!(buffer.len(), 2);
assert!(buffer.contains(&(0, 0)));
assert!(buffer.contains(&(1, 1)));
}
#[tokio::test]
async fn poll_next_many_correctly_loops_around() {
for _ in 0..10 {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(iter([0usize].into_iter())) as UsizeStream);
stream_map.insert(1, Box::pin(iter([0usize, 1].into_iter())) as UsizeStream);
stream_map.insert(2, Box::pin(iter([0usize, 1, 2].into_iter())) as UsizeStream);
let mut buffer = vec![];
let n = poll_fn(|cx| stream_map.poll_next_many(cx, &mut buffer, 3)).await;
assert_eq!(n, 3);
assert_eq!(
std::mem::take(&mut buffer)
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<_>>(),
vec![0, 0, 0]
);
let n = poll_fn(|cx| stream_map.poll_next_many(cx, &mut buffer, 2)).await;
assert_eq!(n, 2);
assert_eq!(
std::mem::take(&mut buffer)
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<_>>(),
vec![1, 1]
);
let n = poll_fn(|cx| stream_map.poll_next_many(cx, &mut buffer, 1)).await;
assert_eq!(n, 1);
assert_eq!(
std::mem::take(&mut buffer)
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<_>>(),
vec![2]
);
}
}
#[tokio::test]
async fn next_many_zero() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(pending()) as UsizeStream);
let n = poll_fn(|cx| pin!(stream_map.next_many(&mut vec![], 0)).poll(cx)).await;
assert_eq!(n, 0);
}
#[tokio::test]
async fn next_many_empty() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
let n = stream_map.next_many(&mut vec![], 1).await;
assert_eq!(n, 0);
}
#[tokio::test]
async fn next_many_pending() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(pending()) as UsizeStream);
let mut is_pending = false;
poll_fn(|cx| {
let poll = pin!(stream_map.next_many(&mut vec![], 1)).poll(cx);
is_pending = poll.is_pending();
Poll::Ready(())
})
.await;
assert!(is_pending);
}
#[tokio::test]
async fn next_many_not_enough() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(iter([0usize].into_iter())) as UsizeStream);
stream_map.insert(1, Box::pin(iter([1usize].into_iter())) as UsizeStream);
let mut buffer = vec![];
let n = poll_fn(|cx| pin!(stream_map.next_many(&mut buffer, 3)).poll(cx)).await;
assert_eq!(n, 2);
assert_eq!(buffer.len(), 2);
assert!(buffer.contains(&(0, 0)));
assert!(buffer.contains(&(1, 1)));
}
#[tokio::test]
async fn next_many_enough() {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(iter([0usize].into_iter())) as UsizeStream);
stream_map.insert(1, Box::pin(iter([1usize].into_iter())) as UsizeStream);
let mut buffer = vec![];
let n = poll_fn(|cx| pin!(stream_map.next_many(&mut buffer, 2)).poll(cx)).await;
assert_eq!(n, 2);
assert_eq!(buffer.len(), 2);
assert!(buffer.contains(&(0, 0)));
assert!(buffer.contains(&(1, 1)));
}
#[tokio::test]
async fn next_many_correctly_loops_around() {
for _ in 0..10 {
let mut stream_map: StreamMap<usize, UsizeStream> = StreamMap::new();
stream_map.insert(0, Box::pin(iter([0usize].into_iter())) as UsizeStream);
stream_map.insert(1, Box::pin(iter([0usize, 1].into_iter())) as UsizeStream);
stream_map.insert(2, Box::pin(iter([0usize, 1, 2].into_iter())) as UsizeStream);
let mut buffer = vec![];
let n = poll_fn(|cx| pin!(stream_map.next_many(&mut buffer, 3)).poll(cx)).await;
assert_eq!(n, 3);
assert_eq!(
std::mem::take(&mut buffer)
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<_>>(),
vec![0, 0, 0]
);
let n = poll_fn(|cx| pin!(stream_map.next_many(&mut buffer, 2)).poll(cx)).await;
assert_eq!(n, 2);
assert_eq!(
std::mem::take(&mut buffer)
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<_>>(),
vec![1, 1]
);
let n = poll_fn(|cx| pin!(stream_map.next_many(&mut buffer, 1)).poll(cx)).await;
assert_eq!(n, 1);
assert_eq!(
std::mem::take(&mut buffer)
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<_>>(),
vec![2]
);
}
}
+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;
+10
View File
@@ -1,3 +1,13 @@
# 0.4.4 (March 14, 2024)
- task: mark `Spawn` as `#[must_use]` ([#6371])
- test: increase MSRV to 1.63 ([#6126])
- test: update category slug ([#5953])
[#5953]: https://github.com/tokio-rs/tokio/pull/5953
[#6126]: https://github.com/tokio-rs/tokio/pull/6126
[#6371]: https://github.com/tokio-rs/tokio/pull/6371
# 0.4.3 (August 23, 2023)
- deps: fix minimum required version of `async-stream` ([#5347])
+1 -1
View File
@@ -4,7 +4,7 @@ name = "tokio-test"
# - Remove path dependencies
# - Update CHANGELOG.md.
# - Create "tokio-test-0.4.x" git tag.
version = "0.4.3"
version = "0.4.4"
edition = "2021"
rust-version = "1.63"
authors = ["Tokio Contributors <[email protected]>"]
+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.
+1
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![warn(
missing_debug_implementations,
missing_docs,
+1 -1
View File
@@ -8,7 +8,7 @@
//! intervals between items.
//!
//! # Usage
//! To use the `StreamMock`, you need to create a builder using[`StreamMockBuilder`]. The builder
//! To use the `StreamMock`, you need to create a builder using [`StreamMockBuilder`]. The builder
//! allows you to enqueue actions such as returning items or waiting for a certain duration.
//!
//! # Example
+1 -2
View File
@@ -25,8 +25,6 @@
//! assert!(task.poll().is_ready(), "Task was not ready!");
//! ```
#![allow(clippy::mutex_atomic)]
use std::future::Future;
use std::mem;
use std::ops;
@@ -51,6 +49,7 @@ pub fn spawn<T>(task: T) -> Spawn<T> {
/// Future spawned on a mock task that can be used to poll the future or stream
/// without needing pinning or context types.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Spawn<T> {
task: MockTask,
future: Pin<Box<T>>,
+33
View File
@@ -1,3 +1,36 @@
# 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
+3 -3
View File
@@ -4,7 +4,7 @@ name = "tokio-util"
# - Remove path dependencies
# - Update CHANGELOG.md.
# - Create "tokio-util-0.7.x" git tag.
version = "0.7.10"
version = "0.7.11"
edition = "2021"
rust-version = "1.63"
authors = ["Tokio Contributors <[email protected]>"]
@@ -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"]
@@ -45,7 +45,7 @@ slab = { version = "0.4.4", optional = true } # Backs `DelayQueue`
tracing = { version = "0.1.25", default-features = false, features = ["std"], optional = true }
[target.'cfg(tokio_unstable)'.dependencies]
hashbrown = { version = "0.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"] }
+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.
+1 -1
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",";
+12 -1
View File
@@ -20,10 +20,21 @@ pin_project! {
/// You can create a `Framed` instance by using the [`Decoder::framed`] adapter, or
/// by using the `new` function seen below.
///
/// # Cancellation safety
///
/// * [`futures_util::sink::SinkExt::send`]: if send is used as the event in a
/// `tokio::select!` statement and some other branch completes first, then it is
/// guaranteed that the message was not sent, but the message itself is lost.
/// * [`tokio_stream::StreamExt::next`]: This method is cancel safe. The returned
/// future only holds onto a reference to the underlying stream, so dropping it will
/// never lose a value.
///
/// [`Stream`]: futures_core::Stream
/// [`Sink`]: futures_sink::Sink
/// [`AsyncRead`]: tokio::io::AsyncRead
/// [`Decoder::framed`]: crate::codec::Decoder::framed()
/// [`futures_util::sink::SinkExt::send`]: futures_util::sink::SinkExt::send
/// [`tokio_stream::StreamExt::next`]: https://docs.rs/tokio-stream/latest/tokio_stream/trait.StreamExt.html#method.next
pub struct Framed<T, U> {
#[pin]
inner: FramedImpl<T, U, RWFrames>
@@ -130,7 +141,7 @@ impl<T, U> Framed<T, U> {
/// things like gzip or TLS, which require both read and write access to the
/// underlying object.
///
/// This objects takes a stream and a readbuffer and a writebuffer. These field
/// This objects takes a stream and a `readbuffer` and a `writebuffer`. These field
/// can be obtained from an existing `Framed` with the [`into_parts`] method.
///
/// If you want to work more directly with the streams and sink, consider
+1 -1
View File
@@ -12,7 +12,6 @@ use std::borrow::{Borrow, BorrowMut};
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use tracing::trace;
pin_project! {
#[derive(Debug)]
@@ -218,6 +217,7 @@ where
// Make sure we've got room for at least one byte to read to ensure
// that we don't get a spurious 0 that looks like EOF.
state.buffer.reserve(1);
#[allow(clippy::blocks_in_conditions)]
let bytect = match poll_read_buf(pinned.inner.as_mut(), cx, &mut state.buffer).map_err(
|err| {
trace!("Got an error, going to errored state");
+10
View File
@@ -14,8 +14,18 @@ use std::task::{Context, Poll};
pin_project! {
/// A [`Stream`] of messages decoded from an [`AsyncRead`].
///
/// For examples of how to use `FramedRead` with a codec, see the
/// examples on the [`codec`] module.
///
/// # Cancellation safety
/// * [`tokio_stream::StreamExt::next`]: This method is cancel safe. The returned
/// future only holds onto a reference to the underlying stream, so dropping it will
/// never lose a value.
///
/// [`Stream`]: futures_core::Stream
/// [`AsyncRead`]: tokio::io::AsyncRead
/// [`codec`]: crate::codec
/// [`tokio_stream::StreamExt::next`]: https://docs.rs/tokio-stream/latest/tokio_stream/trait.StreamExt.html#method.next
pub struct FramedRead<T, D> {
#[pin]
inner: FramedImpl<T, D, ReadFrame>,
+11
View File
@@ -15,7 +15,18 @@ use std::task::{Context, Poll};
pin_project! {
/// A [`Sink`] of frames encoded to an `AsyncWrite`.
///
/// For examples of how to use `FramedWrite` with a codec, see the
/// examples on the [`codec`] module.
///
/// # Cancellation safety
///
/// * [`futures_util::sink::SinkExt::send`]: if send is used as the event in a
/// `tokio::select!` statement and some other branch completes first, then it is
/// guaranteed that the message was not sent, but the message itself is lost.
///
/// [`Sink`]: futures_sink::Sink
/// [`codec`]: crate::codec
/// [`futures_util::sink::SinkExt::send`]: futures_util::sink::SinkExt::send
pub struct FramedWrite<T, E> {
#[pin]
inner: FramedImpl<T, E, WriteFrame>,
+38 -2
View File
@@ -386,6 +386,10 @@ use std::{cmp, fmt, mem};
/// `Builder` enables constructing configured length delimited codecs. Note
/// that not all configuration settings apply to both encoding and decoding. See
/// the documentation for specific methods for more detail.
///
/// Note that the if the value of [`Builder::max_frame_length`] becomes larger than
/// what can actually fit in [`Builder::length_field_length`], it will be clipped to
/// the maximum value that can fit.
#[derive(Debug, Clone, Copy)]
pub struct Builder {
// Maximum frame length
@@ -635,7 +639,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",
@@ -935,8 +938,12 @@ impl Builder {
/// # }
/// ```
pub fn new_codec(&self) -> LengthDelimitedCodec {
let mut builder = *self;
builder.adjust_max_frame_len();
LengthDelimitedCodec {
builder: *self,
builder,
state: DecodeState::Head,
}
}
@@ -1018,6 +1025,35 @@ impl Builder {
self.num_skip
.unwrap_or(self.length_field_offset + self.length_field_len)
}
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);
if self.max_frame_len as u64 > max_allowed_len {
self.max_frame_len = usize::try_from(max_allowed_len).unwrap_or(usize::MAX);
}
}
}
impl Default for Builder {
+1 -1
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.
///
+67 -1
View File
@@ -1,4 +1,4 @@
//! Adaptors from AsyncRead/AsyncWrite to Stream/Sink
//! Adaptors from `AsyncRead`/`AsyncWrite` to Stream/Sink
//!
//! Raw I/O objects work with byte sequences, but higher-level code usually
//! wants to batch these into meaningful chunks, called "frames".
@@ -7,6 +7,71 @@
//! [`AsyncWrite`], to framed streams implementing [`Sink`] and [`Stream`].
//! Framed streams are also known as transports.
//!
//! # Example encoding using `LinesCodec`
//!
//! The following example demonstrates how to use a codec such as [`LinesCodec`] to
//! write framed data. [`FramedWrite`] can be used to achieve this. Data sent to
//! [`FramedWrite`] are first framed according to a specific codec, and then sent to
//! an implementor of [`AsyncWrite`].
//!
//! ```
//! use futures::sink::SinkExt;
//! use tokio_util::codec::LinesCodec;
//! use tokio_util::codec::FramedWrite;
//!
//! #[tokio::main]
//! async fn main() {
//! let buffer = Vec::new();
//! let messages = vec!["Hello", "World"];
//! let encoder = LinesCodec::new();
//!
//! // FramedWrite is a sink which means you can send values into it
//! // asynchronously.
//! let mut writer = FramedWrite::new(buffer, encoder);
//!
//! // To be able to send values into a FramedWrite, you need to bring the
//! // `SinkExt` trait into scope.
//! writer.send(messages[0]).await.unwrap();
//! writer.send(messages[1]).await.unwrap();
//!
//! let buffer = writer.get_ref();
//!
//! assert_eq!(buffer.as_slice(), "Hello\nWorld\n".as_bytes());
//! }
//!```
//!
//! # Example decoding using `LinesCodec`
//! The following example demonstrates how to use a codec such as [`LinesCodec`] to
//! read a stream of framed data. [`FramedRead`] can be used to achieve this. [`FramedRead`]
//! will keep reading from an [`AsyncRead`] implementor until a whole frame, according to a codec,
//! can be parsed.
//!
//!```
//! use tokio_stream::StreamExt;
//! use tokio_util::codec::LinesCodec;
//! use tokio_util::codec::FramedRead;
//!
//! #[tokio::main]
//! async fn main() {
//! let message = "Hello\nWorld".as_bytes();
//! let decoder = LinesCodec::new();
//!
//! // FramedRead can be used to read a stream of values that are framed according to
//! // a codec. FramedRead will read from its input (here `buffer`) until a whole frame
//! // can be parsed.
//! let mut reader = FramedRead::new(message, decoder);
//!
//! // To read values from a FramedRead, you need to bring the
//! // `StreamExt` trait into scope.
//! let frame1 = reader.next().await.unwrap().unwrap();
//! let frame2 = reader.next().await.unwrap().unwrap();
//!
//! assert!(reader.next().await.is_none());
//! assert_eq!(frame1, "Hello");
//! assert_eq!(frame2, "World");
//! }
//! ```
//!
//! # The Decoder trait
//!
//! A [`Decoder`] is used together with [`FramedRead`] or [`Framed`] to turn an
@@ -248,6 +313,7 @@
//! [`AsyncWrite`]: tokio::io::AsyncWrite
//! [`Stream`]: futures_core::Stream
//! [`Sink`]: futures_sink::Sink
//! [`SinkExt`]: futures::sink::SinkExt
//! [`SinkExt::close`]: https://docs.rs/futures/0.3/futures/sink/trait.SinkExt.html#method.close
//! [`FramedRead`]: struct@crate::codec::FramedRead
//! [`FramedWrite`]: struct@crate::codec::FramedWrite
+33
View File
@@ -164,6 +164,39 @@ where
}
}
impl<L, R, Item, Error> futures_sink::Sink<Item> for Either<L, R>
where
L: futures_sink::Sink<Item, Error = Error>,
R: futures_sink::Sink<Item, Error = Error>,
{
type Error = Error;
fn poll_ready(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<std::result::Result<(), Self::Error>> {
delegate_call!(self.poll_ready(cx))
}
fn start_send(self: Pin<&mut Self>, item: Item) -> std::result::Result<(), Self::Error> {
delegate_call!(self.start_send(item))
}
fn poll_flush(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<std::result::Result<(), Self::Error>> {
delegate_call!(self.poll_flush(cx))
}
fn poll_close(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<std::result::Result<(), Self::Error>> {
delegate_call!(self.poll_close(cx))
}
}
#[cfg(test)]
mod tests {
use super::*;
+2 -2
View File
@@ -18,7 +18,7 @@ pin_project! {
}
impl<R, F> InspectReader<R, F> {
/// Create a new InspectReader, wrapping `reader` and calling `f` for the
/// Create a new `InspectReader`, wrapping `reader` and calling `f` for the
/// new data supplied by each read call.
///
/// The closure will only be called with an empty slice if the inner reader
@@ -100,7 +100,7 @@ pin_project! {
}
impl<W, F> InspectWriter<W, F> {
/// Create a new InspectWriter, wrapping `write` and calling `f` for the
/// Create a new `InspectWriter`, wrapping `write` and calling `f` for the
/// data successfully written by each write call.
///
/// The closure `f` will never be called with an empty slice. A vectored
+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;
}
@@ -1,16 +1,16 @@
//! This mod provides the logic for the inner tree structure of the CancellationToken.
//! This mod provides the logic for the inner tree structure of the `CancellationToken`.
//!
//! CancellationTokens are only light handles with references to [`TreeNode`].
//! `CancellationTokens` are only light handles with references to [`TreeNode`].
//! All the logic is actually implemented in the [`TreeNode`].
//!
//! A [`TreeNode`] is part of the cancellation tree and may have one parent and an arbitrary number of
//! children.
//!
//! A [`TreeNode`] can receive the request to perform a cancellation through a CancellationToken.
//! A [`TreeNode`] can receive the request to perform a cancellation through a `CancellationToken`.
//! This cancellation request will cancel the node and all of its descendants.
//!
//! As soon as a node cannot get cancelled any more (because it was already cancelled or it has no
//! more CancellationTokens pointing to it any more), it gets removed from the tree, to keep the
//! more `CancellationTokens` pointing to it any more), it gets removed from the tree, to keep the
//! tree as small as possible.
//!
//! # Invariants
@@ -66,7 +66,7 @@ impl TreeNode {
}
}
/// The data contained inside a TreeNode.
/// The data contained inside a `TreeNode`.
///
/// This struct exists so that the data of the node can be wrapped
/// in a Mutex.
@@ -178,6 +178,8 @@ where
locked_node = node.inner.lock().unwrap();
locked_parent
}
// https://github.com/tokio-rs/tokio/pull/6273#discussion_r1443752911
#[allow(clippy::unnecessary_literal_unwrap)]
Err(TryLockError::Poisoned(err)) => Err(err).unwrap(),
};
@@ -196,7 +198,7 @@ where
/// `parent` MUST have been a parent of the node when they both got locked,
/// otherwise there is a potential for a deadlock as invariant #2 would be violated.
///
/// To acquire the locks for node and parent, use [with_locked_node_and_parent].
/// To acquire the locks for node and parent, use [`with_locked_node_and_parent`].
fn move_children_to_parent(node: &mut Inner, parent: &mut Inner) {
// Pre-allocate in the parent, for performance
parent.children.reserve(node.children.len());
@@ -204,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);
@@ -214,7 +216,7 @@ fn move_children_to_parent(node: &mut Inner, parent: &mut Inner) {
/// Removes a child from the parent.
///
/// `parent` MUST be the parent of `node`.
/// To acquire the locks for node and parent, use [with_locked_node_and_parent].
/// To acquire the locks for node and parent, use [`with_locked_node_and_parent`].
fn remove_child(parent: &mut Inner, mut node: MutexGuard<'_, Inner>) {
// Query the position from where to remove a node
let pos = node.parent_idx;
+1 -1
View File
@@ -303,7 +303,7 @@ impl<T> Clone for PollSender<T> {
}
}
impl<T: Send + 'static> Sink<T> for PollSender<T> {
impl<T: Send> Sink<T> for PollSender<T> {
type Error = PollSendError<T>;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+2 -2
View File
@@ -462,7 +462,7 @@ where
/// * `Some((key, Ok(value)))` if one of the tasks in this `JoinMap` has
/// completed. The `value` is the return value of that ask, and `key` is
/// the key associated with the task.
/// * `Some((key, Err(err))` if one of the tasks in this JoinMap` has
/// * `Some((key, Err(err))` if one of the tasks in this `JoinMap` has
/// panicked or been aborted. `key` is the key associated with the task
/// that panicked or was aborted.
/// * `None` if the `JoinMap` is empty.
@@ -878,7 +878,7 @@ impl<K: Eq> Eq for Key<K> {}
#[derive(Debug, Clone)]
pub struct JoinMapKeys<'a, K, V> {
iter: hashbrown::hash_map::Keys<'a, Key<K>, AbortHandle>,
/// To make it easier to change JoinMap in the future, keep V as a generic
/// To make it easier to change `JoinMap` in the future, keep V as a generic
/// parameter.
_value: PhantomData<&'a V>,
}
-2
View File
@@ -2,9 +2,7 @@
#[cfg(tokio_unstable)]
mod join_map;
#[cfg(not(target_os = "wasi"))]
mod spawn_pinned;
#[cfg(not(target_os = "wasi"))]
pub use spawn_pinned::LocalPoolHandle;
#[cfg(tokio_unstable)]
+1 -1
View File
@@ -23,7 +23,7 @@ use tokio::task::{spawn_local, JoinHandle, LocalSet};
///
/// ```
/// use std::rc::Rc;
/// use tokio::{self, task };
/// use tokio::task;
/// use tokio_util::task::LocalPoolHandle;
///
/// #[tokio::main(flavor = "current_thread")]
+37 -2
View File
@@ -671,6 +671,39 @@ impl<T> DelayQueue<T> {
}
}
/// Returns the deadline of the item associated with `key`.
///
/// Since the queue operates at millisecond granularity, the returned
/// deadline may not exactly match the value that was given when initially
/// inserting the item into the queue.
///
/// # Panics
///
/// This function panics if `key` is not contained by the queue.
///
/// # Examples
///
/// Basic usage
///
/// ```rust
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
///
/// let key1 = delay_queue.insert("foo", Duration::from_secs(5));
/// let key2 = delay_queue.insert("bar", Duration::from_secs(10));
///
/// assert!(delay_queue.deadline(&key1) < delay_queue.deadline(&key2));
/// # }
/// ```
#[track_caller]
pub fn deadline(&self, key: &Key) -> Instant {
self.start + Duration::from_millis(self.slab[*key].when)
}
/// Removes the key from the expired queue or the timer wheel
/// depending on its expiration status.
///
@@ -909,8 +942,10 @@ impl<T> DelayQueue<T> {
self.expired.peek().or_else(|| self.wheel.peek())
}
/// Returns the next time to poll as determined by the wheel
fn next_deadline(&mut self) -> Option<Instant> {
/// Returns the next time to poll as determined by the wheel.
///
/// Note that this does not include deadlines in the `expired` queue.
fn next_deadline(&self) -> Option<Instant> {
self.wheel
.poll_at()
.map(|poll_at| self.start + Duration::from_millis(poll_at))
+30
View File
@@ -8,7 +8,9 @@
//!
//! This type must be used from within the context of the `Runtime`.
use futures_core::Future;
use std::time::Duration;
use tokio::time::Timeout;
mod wheel;
@@ -17,6 +19,34 @@ pub mod delay_queue;
#[doc(inline)]
pub use delay_queue::DelayQueue;
/// A trait which contains a variety of convenient adapters and utilities for `Future`s.
pub trait FutureExt: Future {
/// A wrapper around [`tokio::time::timeout`], with the advantage that it is easier to write
/// fluent call chains.
///
/// # Examples
///
/// ```rust
/// use tokio::{sync::oneshot, time::Duration};
/// use tokio_util::time::FutureExt;
///
/// # async fn dox() {
/// let (tx, rx) = oneshot::channel::<()>();
///
/// let res = rx.timeout(Duration::from_millis(10)).await;
/// assert!(res.is_err());
/// # }
/// ```
fn timeout(self, timeout: Duration) -> Timeout<Self>
where
Self: Sized,
{
tokio::time::timeout(timeout, self)
}
}
impl<T: Future + ?Sized> FutureExt for T {}
// ===== Internal utils =====
enum Round {
+1 -1
View File
@@ -270,7 +270,7 @@ mod test {
for level in 1..5 {
for pos in level..64 {
let a = pos * 64_usize.pow(level as u32);
assert_eq!(pos as usize, slot_for(a as u64, level));
assert_eq!(pos, slot_for(a as u64, level));
}
}
}
-1
View File
@@ -7,7 +7,6 @@ pub(crate) use self::stack::Stack;
use std::borrow::Borrow;
use std::fmt::Debug;
use std::usize;
/// Timing wheel implementation.
///
+6
View File
@@ -0,0 +1,6 @@
macro_rules! trace {
($($arg:tt)*) => {
#[cfg(feature = "tracing")]
tracing::trace!($($arg)*);
};
}
+2 -2
View File
@@ -46,7 +46,7 @@ use std::task::{Context, Poll};
/// # }
/// ```
#[cfg_attr(not(feature = "io"), allow(unreachable_pub))]
pub fn poll_read_buf<T: AsyncRead, B: BufMut>(
pub fn poll_read_buf<T: AsyncRead + ?Sized, B: BufMut>(
io: Pin<&mut T>,
cx: &mut Context<'_>,
buf: &mut B,
@@ -120,7 +120,7 @@ pub fn poll_read_buf<T: AsyncRead, B: BufMut>(
/// [`File`]: tokio::fs::File
/// [vectored writes]: tokio::io::AsyncWrite::poll_write_vectored
#[cfg_attr(not(feature = "io"), allow(unreachable_pub))]
pub fn poll_write_buf<T: AsyncWrite, B: Buf>(
pub fn poll_write_buf<T: AsyncWrite + ?Sized, B: Buf>(
io: Pin<&mut T>,
cx: &mut Context<'_>,
buf: &mut B,
+2 -1
View File
@@ -1,4 +1,4 @@
#![cfg(all(feature = "compat"))]
#![cfg(feature = "compat")]
#![cfg(not(target_os = "wasi"))] // WASI does not support all fs operations
#![warn(rust_2018_idioms)]
@@ -15,6 +15,7 @@ async fn compat_file_seek() -> futures_util::io::Result<()> {
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(temp_file)
.await?
.compat_write();
+60
View File
@@ -689,6 +689,66 @@ fn encode_overflow() {
codec.encode(Bytes::from("hello"), &mut buf).unwrap();
}
#[test]
fn frame_does_not_fit() {
let codec = LengthDelimitedCodec::builder()
.length_field_length(1)
.max_frame_length(256)
.new_codec();
assert_eq!(codec.max_frame_length(), 255);
}
#[test]
fn neg_adjusted_frame_does_not_fit() {
let codec = LengthDelimitedCodec::builder()
.length_field_length(1)
.length_adjustment(-1)
.new_codec();
assert_eq!(codec.max_frame_length(), 254);
}
#[test]
fn pos_adjusted_frame_does_not_fit() {
let codec = LengthDelimitedCodec::builder()
.length_field_length(1)
.length_adjustment(1)
.new_codec();
assert_eq!(codec.max_frame_length(), 256);
}
#[test]
fn max_allowed_frame_fits() {
let codec = LengthDelimitedCodec::builder()
.length_field_length(std::mem::size_of::<usize>())
.max_frame_length(usize::MAX)
.new_codec();
assert_eq!(codec.max_frame_length(), usize::MAX);
}
#[test]
fn smaller_frame_len_not_adjusted() {
let codec = LengthDelimitedCodec::builder()
.max_frame_length(10)
.length_field_length(std::mem::size_of::<usize>())
.new_codec();
assert_eq!(codec.max_frame_length(), 10);
}
#[test]
fn max_allowed_length_field() {
let codec = LengthDelimitedCodec::builder()
.length_field_length(8)
.max_frame_length(usize::MAX)
.new_codec();
assert_eq!(codec.max_frame_length(), usize::MAX);
}
// ===== Test utils =====
struct Mock {
+89 -2
View File
@@ -1,7 +1,10 @@
use futures::future::poll_fn;
use futures::sink::SinkExt;
use tokio::sync::mpsc::channel;
use tokio_test::task::spawn;
use tokio_test::{assert_pending, assert_ready, assert_ready_err, assert_ready_ok};
use tokio_test::{
assert_ok, assert_pending, assert_ready, assert_ready_eq, assert_ready_err, assert_ready_ok,
};
use tokio_util::sync::PollSender;
#[tokio::test]
@@ -29,7 +32,7 @@ async fn simple() {
#[tokio::test]
async fn simple_ref() {
let v = vec![1, 2, 3i32];
let v = [1, 2, 3i32];
let (send, mut recv) = channel(3);
let mut send = PollSender::new(send);
@@ -260,3 +263,87 @@ fn start_send_panics_when_acquiring() {
assert_pending!(reserve.poll());
send.send_item(2).unwrap();
}
#[test]
fn sink_send_then_flush() {
let (send, mut recv) = channel(1);
let mut send = PollSender::new(send);
let mut recv_task = spawn(recv.recv());
assert_pending!(recv_task.poll());
let mut ready = spawn(poll_fn(|cx| send.poll_ready_unpin(cx)));
assert_ready_ok!(ready.poll());
assert_ok!(send.start_send_unpin(()));
let mut ready = spawn(poll_fn(|cx| send.poll_ready_unpin(cx)));
assert_pending!(ready.poll());
let mut flush = spawn(poll_fn(|cx| send.poll_flush_unpin(cx)));
assert_ready_ok!(flush.poll());
// Flushing does not mean that the sender becomes ready.
let mut ready = spawn(poll_fn(|cx| send.poll_ready_unpin(cx)));
assert_pending!(ready.poll());
assert_ready_eq!(recv_task.poll(), Some(()));
assert!(ready.is_woken());
assert_ready_ok!(ready.poll());
}
#[test]
fn sink_send_then_close() {
let (send, mut recv) = channel(1);
let mut send = PollSender::new(send);
let mut recv_task = spawn(recv.recv());
assert_pending!(recv_task.poll());
let mut ready = spawn(poll_fn(|cx| send.poll_ready_unpin(cx)));
assert_ready_ok!(ready.poll());
assert_ok!(send.start_send_unpin(1));
let mut ready = spawn(poll_fn(|cx| send.poll_ready_unpin(cx)));
assert_pending!(ready.poll());
assert!(recv_task.is_woken());
assert_ready_eq!(recv_task.poll(), Some(1));
assert!(ready.is_woken());
assert_ready_ok!(ready.poll());
drop(recv_task);
let mut recv_task = spawn(recv.recv());
assert_pending!(recv_task.poll());
assert_ok!(send.start_send_unpin(2));
let mut close = spawn(poll_fn(|cx| send.poll_close_unpin(cx)));
assert_ready_ok!(close.poll());
assert!(recv_task.is_woken());
assert_ready_eq!(recv_task.poll(), Some(2));
drop(recv_task);
let mut recv_task = spawn(recv.recv());
assert_ready_eq!(recv_task.poll(), None);
}
#[test]
fn sink_send_ref() {
let data = "data".to_owned();
let (send, mut recv) = channel(1);
let mut send = PollSender::new(send);
let mut recv_task = spawn(recv.recv());
assert_pending!(recv_task.poll());
let mut ready = spawn(poll_fn(|cx| send.poll_ready_unpin(cx)));
assert_ready_ok!(ready.poll());
assert_ok!(send.start_send_unpin(data.as_str()));
let mut flush = spawn(poll_fn(|cx| send.poll_flush_unpin(cx)));
assert_ready_ok!(flush.poll());
assert_ready_eq!(recv_task.poll(), Some("data"));
}
+1 -2
View File
@@ -1,5 +1,6 @@
#![warn(rust_2018_idioms)]
#![cfg(all(feature = "full", not(target_os = "wasi")))] // Wasi doesn't support panic recovery
#![cfg(panic = "unwind")]
use parking_lot::{const_mutex, Mutex};
use std::error::Error;
@@ -76,7 +77,6 @@ fn poll_sender_send_item_panic_caller() -> Result<(), Box<dyn Error>> {
}
#[test]
fn local_pool_handle_new_panic_caller() -> Result<(), Box<dyn Error>> {
let panic_location_file = test_panic(|| {
let _ = LocalPoolHandle::new(0);
@@ -89,7 +89,6 @@ fn local_pool_handle_new_panic_caller() -> Result<(), Box<dyn Error>> {
}
#[test]
fn local_pool_handle_spawn_pinned_by_idx_panic_caller() -> Result<(), Box<dyn Error>> {
let panic_location_file = test_panic(|| {
let rt = basic();
+4 -2
View File
@@ -31,7 +31,7 @@ fn can_drop_future_and_still_get_output() {
let pool = task::LocalPoolHandle::new(1);
let (sender, receiver) = std::sync::mpsc::channel();
let _ = pool.spawn_pinned(move || {
pool.spawn_pinned(move || {
// Rc is !Send + !Sync
let local_data = Rc::new("test");
@@ -71,6 +71,7 @@ async fn can_spawn_multiple_futures() {
/// A panic in the spawned task causes the join handle to return an error.
/// But, you can continue to spawn tasks.
#[tokio::test]
#[cfg(panic = "unwind")]
async fn task_panic_propagates() {
let pool = task::LocalPoolHandle::new(1);
@@ -95,6 +96,7 @@ async fn task_panic_propagates() {
/// A panic during task creation causes the join handle to return an error.
/// But, you can continue to spawn tasks.
#[tokio::test]
#[cfg(panic = "unwind")]
async fn callback_panic_does_not_kill_worker() {
let pool = task::LocalPoolHandle::new(1);
@@ -209,7 +211,7 @@ async fn spawn_by_idx() {
},
0,
);
let _ = pool.spawn_pinned_by_idx(
pool.spawn_pinned_by_idx(
|| async move {
barrier2.wait().await;
std::thread::current().id()
+1
View File
@@ -1,3 +1,4 @@
#![allow(unknown_lints, unexpected_cfgs)]
#![warn(rust_2018_idioms)]
#![cfg(all(feature = "rt", tokio_unstable))]
+2
View File
@@ -805,6 +805,7 @@ async fn item_expiry_greater_than_wheel() {
#[cfg_attr(target_os = "wasi", ignore = "FIXME: Does not seem to work with WASI")]
#[tokio::test(start_paused = true)]
#[cfg(panic = "unwind")]
async fn remove_after_compact() {
let now = Instant::now();
let mut queue = DelayQueue::new();
@@ -822,6 +823,7 @@ async fn remove_after_compact() {
#[cfg_attr(target_os = "wasi", ignore = "FIXME: Does not seem to work with WASI")]
#[tokio::test(start_paused = true)]
#[cfg(panic = "unwind")]
async fn remove_after_compact_poll() {
let now = Instant::now();
let mut queue = task::spawn(DelayQueue::new());
+14 -2
View File
@@ -14,7 +14,13 @@ use std::io;
use std::sync::Arc;
#[cfg_attr(
any(target_os = "macos", target_os = "ios", target_os = "tvos"),
any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "visionos"
),
allow(unused_assignments)
)]
#[tokio::test]
@@ -44,7 +50,13 @@ async fn send_framed_byte_codec() -> std::io::Result<()> {
b_soc = b.into_inner();
}
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))]
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "visionos"
)))]
// test sending & receiving an empty message
{
let mut a = UdpFramed::new(a_soc, ByteCodec);
+200 -4
View File
@@ -1,3 +1,180 @@
# 1.37.0 (March 28th, 2024)
### Added
- fs: add `set_max_buf_size` to `tokio::fs::File` ([#6411])
- io: add `try_new` and `try_with_interest` to `AsyncFd` ([#6345])
- sync: add `forget_permits` method to semaphore ([#6331])
- sync: add `is_closed`, `is_empty`, and `len` to mpsc receivers ([#6348])
- sync: add a `rwlock()` method to owned `RwLock` guards ([#6418])
- sync: expose strong and weak counts of mpsc sender handles ([#6405])
- sync: implement `Clone` for `watch::Sender` ([#6388])
- task: add `TaskLocalFuture::take_value` ([#6340])
- task: implement `FromIterator` for `JoinSet` ([#6300])
### Changed
- io: make `io::split` use a mutex instead of a spinlock ([#6403])
### Fixed
- docs: fix docsrs build without net feature ([#6360])
- macros: allow select with only else branch ([#6339])
- runtime: fix leaking registration entries when os registration fails ([#6329])
### Documented
- io: document cancel safety of `AsyncBufReadExt::fill_buf` ([#6431])
- io: document cancel safety of `AsyncReadExt`'s primitive read functions ([#6337])
- runtime: add doc link from `Runtime` to `#[tokio::main]` ([#6366])
- runtime: make the `enter` example deterministic ([#6351])
- sync: add Semaphore example for limiting the number of outgoing requests ([#6419])
- sync: fix missing period in broadcast docs ([#6377])
- sync: mark `mpsc::Sender::downgrade` with `#[must_use]` ([#6326])
- sync: reorder `const_new` before `new_with` ([#6392])
- sync: update watch channel docs ([#6395])
- task: fix documentation links ([#6336])
### Changed (unstable)
- runtime: include task `Id` in taskdumps ([#6328])
- runtime: panic if `unhandled_panic` is enabled when not supported ([#6410])
[#6300]: https://github.com/tokio-rs/tokio/pull/6300
[#6326]: https://github.com/tokio-rs/tokio/pull/6326
[#6328]: https://github.com/tokio-rs/tokio/pull/6328
[#6329]: https://github.com/tokio-rs/tokio/pull/6329
[#6331]: https://github.com/tokio-rs/tokio/pull/6331
[#6336]: https://github.com/tokio-rs/tokio/pull/6336
[#6337]: https://github.com/tokio-rs/tokio/pull/6337
[#6339]: https://github.com/tokio-rs/tokio/pull/6339
[#6340]: https://github.com/tokio-rs/tokio/pull/6340
[#6345]: https://github.com/tokio-rs/tokio/pull/6345
[#6348]: https://github.com/tokio-rs/tokio/pull/6348
[#6351]: https://github.com/tokio-rs/tokio/pull/6351
[#6360]: https://github.com/tokio-rs/tokio/pull/6360
[#6366]: https://github.com/tokio-rs/tokio/pull/6366
[#6377]: https://github.com/tokio-rs/tokio/pull/6377
[#6388]: https://github.com/tokio-rs/tokio/pull/6388
[#6392]: https://github.com/tokio-rs/tokio/pull/6392
[#6395]: https://github.com/tokio-rs/tokio/pull/6395
[#6403]: https://github.com/tokio-rs/tokio/pull/6403
[#6405]: https://github.com/tokio-rs/tokio/pull/6405
[#6410]: https://github.com/tokio-rs/tokio/pull/6410
[#6411]: https://github.com/tokio-rs/tokio/pull/6411
[#6418]: https://github.com/tokio-rs/tokio/pull/6418
[#6419]: https://github.com/tokio-rs/tokio/pull/6419
[#6431]: https://github.com/tokio-rs/tokio/pull/6431
# 1.36.0 (February 2nd, 2024)
### Added
- io: add `tokio::io::Join` ([#6220])
- io: implement `AsyncWrite` for `Empty` ([#6235])
- net: add support for anonymous unix pipes ([#6127])
- net: add `UnixSocket` ([#6290])
- net: expose keepalive option on `TcpSocket` ([#6311])
- sync: add `{Receiver,UnboundedReceiver}::poll_recv_many` ([#6236])
- sync: add `Sender::{try_,}reserve_many` ([#6205])
- sync: add `watch::Receiver::mark_unchanged` ([#6252])
- task: add `JoinSet::try_join_next` ([#6280])
### Changed
- io: make `copy` cooperative ([#6265])
- io: make `repeat` and `sink` cooperative ([#6254])
- io: simplify check for empty slice ([#6293])
- process: use pidfd on Linux when available ([#6152])
- sync: use AtomicBool in broadcast channel future ([#6298])
### Documented
- io: clarify `clear_ready` docs ([#6304])
- net: document that `*Fd` traits on `TcpSocket` are unix-only ([#6294])
- sync: document FIFO behavior of `tokio::sync::Mutex` ([#6279])
- chore: typographic improvements ([#6262])
- runtime: remove obsolete comment ([#6303])
- task: fix typo ([#6261])
[#6220]: https://github.com/tokio-rs/tokio/pull/6220
[#6235]: https://github.com/tokio-rs/tokio/pull/6235
[#6127]: https://github.com/tokio-rs/tokio/pull/6127
[#6290]: https://github.com/tokio-rs/tokio/pull/6290
[#6311]: https://github.com/tokio-rs/tokio/pull/6311
[#6236]: https://github.com/tokio-rs/tokio/pull/6236
[#6205]: https://github.com/tokio-rs/tokio/pull/6205
[#6252]: https://github.com/tokio-rs/tokio/pull/6252
[#6280]: https://github.com/tokio-rs/tokio/pull/6280
[#6265]: https://github.com/tokio-rs/tokio/pull/6265
[#6254]: https://github.com/tokio-rs/tokio/pull/6254
[#6293]: https://github.com/tokio-rs/tokio/pull/6293
[#6238]: https://github.com/tokio-rs/tokio/pull/6238
[#6152]: https://github.com/tokio-rs/tokio/pull/6152
[#6298]: https://github.com/tokio-rs/tokio/pull/6298
[#6262]: https://github.com/tokio-rs/tokio/pull/6262
[#6303]: https://github.com/tokio-rs/tokio/pull/6303
[#6261]: https://github.com/tokio-rs/tokio/pull/6261
[#6304]: https://github.com/tokio-rs/tokio/pull/6304
[#6294]: https://github.com/tokio-rs/tokio/pull/6294
[#6279]: https://github.com/tokio-rs/tokio/pull/6279
# 1.35.1 (December 19, 2023)
This is a forward part of a change that was backported to 1.25.3.
### Fixed
- io: add budgeting to `tokio::runtime::io::registration::async_io` ([#6221])
[#6221]: https://github.com/tokio-rs/tokio/pull/6221
# 1.35.0 (December 8th, 2023)
### Added
- net: add Apple watchOS support ([#6176])
### Changed
- io: drop the `Sized` requirements from `AsyncReadExt.read_buf` ([#6169])
- runtime: make `Runtime` unwind safe ([#6189])
- runtime: reduce the lock contention in task spawn ([#6001])
- tokio: update nix dependency to 0.27.1 ([#6190])
### Fixed
- chore: make `--cfg docsrs` work without net feature ([#6166])
- chore: use relaxed load for `unsync_load` on miri ([#6179])
- runtime: handle missing context on wake ([#6148])
- taskdump: fix taskdump cargo config example ([#6150])
- taskdump: skip notified tasks during taskdumps ([#6194])
- tracing: avoid creating resource spans with current parent, use a None parent instead ([#6107])
- tracing: make task span explicit root ([#6158])
### Documented
- io: flush in `AsyncWriteExt` examples ([#6149])
- runtime: document fairness guarantees and current behavior ([#6145])
- task: document cancel safety of `LocalSet::run_until` ([#6147])
[#6001]: https://github.com/tokio-rs/tokio/pull/6001
[#6107]: https://github.com/tokio-rs/tokio/pull/6107
[#6144]: https://github.com/tokio-rs/tokio/pull/6144
[#6145]: https://github.com/tokio-rs/tokio/pull/6145
[#6147]: https://github.com/tokio-rs/tokio/pull/6147
[#6148]: https://github.com/tokio-rs/tokio/pull/6148
[#6149]: https://github.com/tokio-rs/tokio/pull/6149
[#6150]: https://github.com/tokio-rs/tokio/pull/6150
[#6158]: https://github.com/tokio-rs/tokio/pull/6158
[#6166]: https://github.com/tokio-rs/tokio/pull/6166
[#6169]: https://github.com/tokio-rs/tokio/pull/6169
[#6176]: https://github.com/tokio-rs/tokio/pull/6176
[#6179]: https://github.com/tokio-rs/tokio/pull/6179
[#6189]: https://github.com/tokio-rs/tokio/pull/6189
[#6190]: https://github.com/tokio-rs/tokio/pull/6190
[#6194]: https://github.com/tokio-rs/tokio/pull/6194
# 1.34.0 (November 19th, 2023)
### Fixed
@@ -107,6 +284,16 @@
[#6056]: https://github.com/tokio-rs/tokio/pull/6056
[#6058]: https://github.com/tokio-rs/tokio/pull/6058
# 1.32.1 (December 19, 2023)
This is a forward part of a change that was backported to 1.25.3.
### Fixed
- io: add budgeting to `tokio::runtime::io::registration::async_io` ([#6221])
[#6221]: https://github.com/tokio-rs/tokio/pull/6221
# 1.32.0 (August 16, 2023)
### Fixed
@@ -469,6 +656,13 @@ This release bumps the MSRV of Tokio to 1.56. ([#5559])
[#5513]: https://github.com/tokio-rs/tokio/pull/5513
[#5517]: https://github.com/tokio-rs/tokio/pull/5517
# 1.25.3 (December 17th, 2023)
### Fixed
- io: add budgeting to `tokio::runtime::io::registration::async_io` ([#6221])
[#6221]: https://github.com/tokio-rs/tokio/pull/6221
# 1.25.2 (September 22, 2023)
Forward ports 1.20.6 changes.
@@ -1547,7 +1741,9 @@ Fixes a missed edge case from 1.8.1.
### Fixed
- runtime: drop canceled future on next poll (#3965)
- runtime: drop canceled future on next poll ([#3965])
[#3965]: https://github.com/tokio-rs/tokio/pull/3965
# 1.8.1 (July 6, 2021)
@@ -1568,7 +1764,7 @@ Forward ports 1.5.1 fixes.
- net: add ready/try methods to `NamedPipe{Client,Server}` ([#3866], [#3899])
- sync: add `watch::Receiver::borrow_and_update` ([#3813])
- sync: implement `From<T>` for `OnceCell<T>` ([#3877])
- time: allow users to specify Interval behaviour when delayed ([#3721])
- time: allow users to specify Interval behavior when delayed ([#3721])
### Added (unstable)
@@ -1582,7 +1778,7 @@ Forward ports 1.5.1 fixes.
- doc: document cancellation safety ([#3900])
- time: add wait alias to sleep ([#3897])
- time: document auto-advancing behaviour of runtime ([#3763])
- time: document auto-advancing behavior of runtime ([#3763])
[#3163]: https://github.com/tokio-rs/tokio/pull/3163
[#3721]: https://github.com/tokio-rs/tokio/pull/3721
@@ -1829,7 +2025,7 @@ a kernel bug. ([#3803])
- doc: doc aliases for pre-1.0 function names ([#3523])
- io: fix typos ([#3541])
- io: note the EOF behaviour of `read_until` ([#3536])
- io: note the EOF behavior of `read_until` ([#3536])
- io: update `AsyncRead::poll_read` doc ([#3557])
- net: update `UdpSocket` splitting doc ([#3517])
- runtime: add link to `LocalSet` on `new_current_thread` ([#3508])
+14 -4
View File
@@ -6,7 +6,7 @@ name = "tokio"
# - README.md
# - Update CHANGELOG.md.
# - Create "v1.x.y" git tag.
version = "1.34.0"
version = "1.37.0"
edition = "2021"
rust-version = "1.63"
authors = ["Tokio Contributors <[email protected]>"]
@@ -89,7 +89,7 @@ test-util = ["rt", "sync", "time"]
time = []
[dependencies]
tokio-macros = { version = "~2.2.0", path = "../tokio-macros", optional = true }
tokio-macros = { version = "~2.3.0", path = "../tokio-macros", optional = true }
pin-project-lite = "0.2.11"
@@ -118,7 +118,7 @@ signal-hook-registry = { version = "1.1.1", optional = true }
[target.'cfg(unix)'.dev-dependencies]
libc = { version = "0.2.149" }
nix = { version = "0.26", default-features = false, features = ["fs", "socket"] }
nix = { version = "0.29.0", default-features = false, features = ["aio", "fs", "socket"] }
[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.48"
@@ -149,7 +149,7 @@ rand = "0.8.0"
wasm-bindgen-test = "0.3.0"
[target.'cfg(target_os = "freebsd")'.dev-dependencies]
mio-aio = { version = "0.7.0", features = ["tokio"] }
mio-aio = { version = "0.9.0", features = ["tokio"] }
[target.'cfg(loom)'.dev-dependencies]
loom = { version = "0.7", features = ["futures", "checkpoint"] }
@@ -164,3 +164,13 @@ rustc-args = ["--cfg", "tokio_unstable", "--cfg", "tokio_taskdump"]
[package.metadata.playground]
features = ["full", "test-util"]
[package.metadata.cargo_check_external_types]
# The following are types that are allowed to be exposed in Tokio's public API.
# The standard library is allowed by default.
allowed_external_types = [
"bytes::buf::buf_impl::Buf",
"bytes::buf::buf_mut::BufMut",
"tokio_macros::*",
]
+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.
+5 -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.34.0", features = ["full"] }
tokio = { version = "1.37.0", features = ["full"] }
```
Then, on your main.rs:
@@ -215,18 +215,18 @@ 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.25.x` - LTS release until March 2024. (MSRV 1.49)
* `1.32.x` - LTS release until September 2024. (MSRV 1.63)
* `1.36.x` - LTS release until March 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
use an LTS release.
To use a fixed minor version, you can specify the version with a tilde. For
example, to specify that you wish to use the newest `1.25.x` patch release, you
example, to specify that you wish to use the newest `1.32.x` patch release, you
can use the following dependency specification:
```text
tokio = { version = "~1.25", features = [...] }
tokio = { version = "~1.32", features = [...] }
```
### Previous LTS releases
@@ -235,6 +235,7 @@ tokio = { version = "~1.25", features = [...] }
* `1.14.x` - LTS release until June 2022.
* `1.18.x` - LTS release until June 2023.
* `1.20.x` - LTS release until September 2023.
* `1.25.x` - LTS release until March 2024.
## License
-11
View File
@@ -1,11 +0,0 @@
# This config file is for the `cargo-check-external-types` tool that is run in CI.
# The following are types that are allowed to be exposed in Tokio's public API.
# The standard library is allowed by default.
allowed_external_types = [
"bytes::buf::buf_impl::Buf",
"bytes::buf::buf_mut::BufMut",
"tokio_macros::*",
]
+2
View File
@@ -20,6 +20,7 @@
#[derive(Debug)]
pub enum NotDefinedHere {}
#[cfg(feature = "net")]
impl mio::event::Source for NotDefinedHere {
fn register(
&mut self,
@@ -42,4 +43,5 @@ impl mio::event::Source for NotDefinedHere {
}
}
#[cfg(feature = "net")]
pub mod os;

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