mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-16 12:06:55 +02:00
cargo update tokio >= 1.24 (#1842)
This commit is contained in:
parent
39f3f5b2d9
commit
67a7534c21
1337 changed files with 813685 additions and 228172 deletions
84
zeroidc/Cargo.lock
generated
84
zeroidc/Cargo.lock
generated
|
@ -530,14 +530,14 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
|||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.3"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
|
||||
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -871,7 +871,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys",
|
||||
"windows-sys 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1086,19 +1086,19 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.19.2"
|
||||
version = "1.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
|
||||
checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"winapi",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1368,43 +1368,100 @@ version = "0.36.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_msvc 0.36.1",
|
||||
"windows_i686_gnu 0.36.1",
|
||||
"windows_i686_msvc 0.36.1",
|
||||
"windows_x86_64_gnu 0.36.1",
|
||||
"windows_x86_64_msvc 0.36.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc 0.42.0",
|
||||
"windows_i686_gnu 0.42.0",
|
||||
"windows_i686_msvc 0.42.0",
|
||||
"windows_x86_64_gnu 0.42.0",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
|
@ -1427,5 +1484,6 @@ dependencies = [
|
|||
"serde",
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
|
|
@ -18,6 +18,7 @@ serde = "1.0"
|
|||
time = { version = "0.3", features = ["formatting"] }
|
||||
bytes = "1.1"
|
||||
thiserror = "1"
|
||||
tokio = { version = ">=1.24" }
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.20"
|
||||
|
|
2
zeroidc/vendor/mio/.cargo-checksum.json
vendored
2
zeroidc/vendor/mio/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
32
zeroidc/vendor/mio/CHANGELOG.md
vendored
32
zeroidc/vendor/mio/CHANGELOG.md
vendored
|
@ -1,3 +1,33 @@
|
|||
# 0.8.5
|
||||
|
||||
## Changed
|
||||
|
||||
* Updated `windows-sys` to 0.42.0
|
||||
(https://github.com/tokio-rs/mio/pull/1624).
|
||||
* Officially document Wine as not supported, some people claimed it worked,
|
||||
other claims it doesn't, but nobody stepped up to fix the problem
|
||||
(https://github.com/tokio-rs/mio/pull/1596).
|
||||
* Switch to GitHub Actions
|
||||
(https://github.com/tokio-rs/mio/pull/1598, https://github.com/tokio-rs/mio/pull/1601).
|
||||
* Documented the current Poll::poll time behaviour
|
||||
(https://github.com/tokio-rs/mio/pull/1603).
|
||||
|
||||
## Fixed
|
||||
|
||||
* Timeout less than one millisecond becoming zero millsiconds
|
||||
(https://github.com/tokio-rs/mio/pull/1615, https://github.com/tokio-rs/mio/pull/1616)
|
||||
* Undefined reference to `epoll\_create1` on Android API level < 21.
|
||||
(https://github.com/tokio-rs/mio/pull/1590).
|
||||
|
||||
# 0.8.4
|
||||
|
||||
## Added
|
||||
|
||||
* Support `Registery::try_clone` on `wasm32-wasi`
|
||||
(https://github.com/tokio-rs/mio/pull/1576).
|
||||
* Add docs about polling without registering event sources
|
||||
(https://github.com/tokio-rs/mio/pull/1585).
|
||||
|
||||
# 0.8.3
|
||||
|
||||
## Changed
|
||||
|
@ -12,7 +42,7 @@
|
|||
* Improved support for Redox, making it possible to run on stable Rust
|
||||
(https://github.com/tokio-rs/mio/pull/1555).
|
||||
* Don't ignore EAGAIN in UDS connect call
|
||||
(https://github.com/tokio-rs/mio/pull/)1564.
|
||||
(https://github.com/tokio-rs/mio/pull/1564).
|
||||
* Documentation of `TcpStream::connect`
|
||||
(https://github.com/tokio-rs/mio/pull/1565).
|
||||
|
||||
|
|
84
zeroidc/vendor/mio/Cargo.lock
generated
vendored
84
zeroidc/vendor/mio/Cargo.lock
generated
vendored
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -17,58 +19,57 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.122"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.16"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.3"
|
||||
version = "0.8.5"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"libc",
|
||||
"log",
|
||||
"rand",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.4"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -90,21 +91,6 @@ dependencies = [
|
|||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -113,43 +99,57 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f375ae76a43fd649c5a3482a4a3e28eced2267adaefa55422bf7e92696a7dac5"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.0"
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bee8cd327bbef19bf86d30bd66379f57905166d3103b0e2eff4a491b85e421d"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b759cc6e3d97970c98cffe461739e89ab6d424ba5e2e7d3b9b05a2d56116057"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0cee91bff283876711f91e7db0aa234438bc663a9d8304596df00b0a6fd6ef"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51e8c6f778aa4383b033ff785191aea0f1ebeceedc160c2c92f944ef7e191476"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dd6a8b0b1ea4331e4db47192729fce42ac8a110fd22bb3abac555d8d7700f29"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
|
|
7
zeroidc/vendor/mio/Cargo.toml
vendored
7
zeroidc/vendor/mio/Cargo.toml
vendored
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "mio"
|
||||
version = "0.8.3"
|
||||
version = "0.8.5"
|
||||
authors = [
|
||||
"Carl Lerche <me@carllerche.com>",
|
||||
"Thomas de Zeeuw <thomasdezeeuw@gmail.com>",
|
||||
|
@ -47,6 +47,7 @@ rustdoc-args = [
|
|||
targets = [
|
||||
"aarch64-apple-ios",
|
||||
"aarch64-linux-android",
|
||||
"wasm32-wasi",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-pc-windows-msvc",
|
||||
"x86_64-unknown-dragonfly",
|
||||
|
@ -115,11 +116,11 @@ version = "0.11.0"
|
|||
version = "0.2.121"
|
||||
|
||||
[target."cfg(windows)".dependencies.windows-sys]
|
||||
version = "0.36"
|
||||
version = "0.42"
|
||||
features = [
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_Foundation",
|
||||
"Win32_Networking_WinSock",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_System_IO",
|
||||
"Win32_System_WindowsProgramming",
|
||||
]
|
||||
|
|
10
zeroidc/vendor/mio/README.md
vendored
10
zeroidc/vendor/mio/README.md
vendored
|
@ -6,15 +6,15 @@ overhead as possible over the OS abstractions.
|
|||
|
||||
[![Crates.io][crates-badge]][crates-url]
|
||||
[![MIT licensed][mit-badge]][mit-url]
|
||||
[![Build Status][azure-badge]][azure-url]
|
||||
[![Build Status][actions-badge]][actions-url]
|
||||
[![Build Status][cirrus-badge]][cirrus-url]
|
||||
|
||||
[crates-badge]: https://img.shields.io/crates/v/mio.svg
|
||||
[crates-url]: https://crates.io/crates/mio
|
||||
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[mit-url]: LICENSE
|
||||
[azure-badge]: https://dev.azure.com/tokio-rs/Tokio/_apis/build/status/tokio-rs.mio?branchName=master
|
||||
[azure-url]: https://dev.azure.com/tokio-rs/Tokio/_build/latest?definitionId=2&branchName=master
|
||||
[actions-badge]: https://github.com/tokio-rs/mio/workflows/CI/badge.svg
|
||||
[actions-url]: https://github.com/tokio-rs/mio/actions?query=workflow%3ACI+branch%3Amaster
|
||||
[cirrus-badge]: https://api.cirrus-ci.com/github/tokio-rs/mio.svg
|
||||
[cirrus-url]: https://cirrus-ci.com/github/tokio-rs/mio
|
||||
|
||||
|
@ -139,7 +139,6 @@ Currently supported platforms:
|
|||
* Windows
|
||||
* iOS
|
||||
* macOS
|
||||
* Wine (version 6.11+, see [issue #1444])
|
||||
|
||||
There are potentially others. If you find that Mio works on another
|
||||
platform, submit a PR to update the list!
|
||||
|
@ -152,15 +151,16 @@ The Windows implementation for polling sockets is using the [wepoll] strategy.
|
|||
This uses the Windows AFD system to access socket readiness events.
|
||||
|
||||
[wepoll]: https://github.com/piscisaureus/wepoll
|
||||
[issue #1444]: https://github.com/tokio-rs/mio/issues/1444
|
||||
|
||||
### Unsupported
|
||||
|
||||
* Haiku, see [issue #1472]
|
||||
* Solaris, see [issue #1152]
|
||||
* Wine, see [issue #1444]
|
||||
|
||||
[issue #1472]: https://github.com/tokio-rs/mio/issues/1472
|
||||
[issue #1152]: https://github.com/tokio-rs/mio/issues/1152
|
||||
[issue #1444]: https://github.com/tokio-rs/mio/issues/1444
|
||||
|
||||
## Community
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// cargo run --example tcp_listenfd_server --features="os-poll net"
|
||||
// or with wasi:
|
||||
// cargo +nightly build --target wasm32-wasi --example tcp_listenfd_server --features="os-poll net"
|
||||
// wasmtime run --tcplisten 127.0.0.1:9000 --env 'LISTEN_FDS=1' target/wasm32-wasi/debug/examples/tcp_server.wasm
|
||||
// wasmtime run --tcplisten 127.0.0.1:9000 --env 'LISTEN_FDS=1' target/wasm32-wasi/debug/examples/tcp_listenfd_server.wasm
|
||||
|
||||
use mio::event::Event;
|
||||
use mio::net::{TcpListener, TcpStream};
|
||||
|
@ -48,7 +48,6 @@ fn main() -> io::Result<()> {
|
|||
// Setup the TCP server socket.
|
||||
let mut server = {
|
||||
let stdlistener = get_first_listen_fd_listener().unwrap();
|
||||
stdlistener.set_nonblocking(true)?;
|
||||
println!("Using preopened socket FD 3");
|
||||
println!("You can connect to the server using `nc`:");
|
||||
match stdlistener.local_addr() {
|
||||
|
@ -78,7 +77,7 @@ fn main() -> io::Result<()> {
|
|||
// indicates we can accept an connection.
|
||||
let (mut connection, address) = match server.accept() {
|
||||
Ok((connection, address)) => (connection, address),
|
||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
Err(ref e) if would_block(e) => {
|
||||
// If we get a `WouldBlock` error we know our
|
||||
// listener has no more incoming connections queued,
|
||||
// so we can return to polling and wait for some
|
||||
|
|
20
zeroidc/vendor/mio/src/net/tcp/stream.rs
vendored
20
zeroidc/vendor/mio/src/net/tcp/stream.rs
vendored
|
@ -269,49 +269,49 @@ impl TcpStream {
|
|||
|
||||
impl Read for TcpStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read(buf))
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Read for &'a TcpStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read(buf))
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for TcpStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write(buf))
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|inner| (&*inner).flush())
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for &'a TcpStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write(buf))
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|inner| (&*inner).flush())
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
20
zeroidc/vendor/mio/src/net/uds/stream.rs
vendored
20
zeroidc/vendor/mio/src/net/uds/stream.rs
vendored
|
@ -144,49 +144,49 @@ impl UnixStream {
|
|||
|
||||
impl Read for UnixStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read(buf))
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Read for &'a UnixStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read(buf))
|
||||
self.inner.do_io(|mut inner| inner.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for UnixStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write(buf))
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|inner| (&*inner).flush())
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for &'a UnixStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write(buf))
|
||||
self.inner.do_io(|mut inner| inner.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
|
||||
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|inner| (&*inner).flush())
|
||||
self.inner.do_io(|mut inner| inner.flush())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
34
zeroidc/vendor/mio/src/poll.rs
vendored
34
zeroidc/vendor/mio/src/poll.rs
vendored
|
@ -187,6 +187,28 @@ use std::{fmt, io};
|
|||
/// operations to go through Mio otherwise it is not able to update it's
|
||||
/// internal state properly and won't generate events.
|
||||
///
|
||||
/// ### Polling without registering event sources
|
||||
///
|
||||
///
|
||||
/// *The following is **not** guaranteed, just a description of the current
|
||||
/// situation!* Mio is allowed to change the following without it being
|
||||
/// considered a breaking change, don't depend on this, it's just here to inform
|
||||
/// the user. On platforms that use epoll, kqueue or IOCP (see implementation
|
||||
/// notes below) polling without previously registering [event sources] will
|
||||
/// result in sleeping forever, only a process signal will be able to wake up
|
||||
/// the thread.
|
||||
///
|
||||
/// On WASM/WASI this is different as it doesn't support process signals,
|
||||
/// furthermore the WASI specification doesn't specify a behaviour in this
|
||||
/// situation, thus it's up to the implementation what to do here. As an
|
||||
/// example, the wasmtime runtime will return `EINVAL` in this situation, but
|
||||
/// different runtimes may return different results. If you have further
|
||||
/// insights or thoughts about this situation (and/or how Mio should handle it)
|
||||
/// please add you comment to [pull request#1580].
|
||||
///
|
||||
/// [event sources]: crate::event::Source
|
||||
/// [pull request#1580]: https://github.com/tokio-rs/mio/pull/1580
|
||||
///
|
||||
/// # Implementation notes
|
||||
///
|
||||
/// `Poll` is backed by the selector provided by the operating system.
|
||||
|
@ -241,6 +263,13 @@ impl Poll {
|
|||
/// the system selector. If this syscall fails, `Poll::new` will return
|
||||
/// with the error.
|
||||
///
|
||||
/// close-on-exec flag is set on the file descriptors used by the selector to prevent
|
||||
/// leaking it to executed processes. However, on some systems such as
|
||||
/// old Linux systems that don't support `epoll_create1` syscall it is done
|
||||
/// non-atomically, so a separate thread executing in parallel to this
|
||||
/// function may accidentally leak the file descriptor if it executes a
|
||||
/// new process before this function returns.
|
||||
///
|
||||
/// See [struct] level docs for more details.
|
||||
///
|
||||
/// [struct]: struct.Poll.html
|
||||
|
@ -320,6 +349,10 @@ impl Poll {
|
|||
/// of Mio would automatically retry the poll call if it was interrupted
|
||||
/// (if `EINTR` was returned).
|
||||
///
|
||||
/// Currently if the `timeout` elapses without any readiness events
|
||||
/// triggering this will return `Ok(())`. However we're not guaranteeing
|
||||
/// this behaviour as this depends on the OS.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A basic example -- establishing a `TcpStream` connection.
|
||||
|
@ -635,7 +668,6 @@ impl Registry {
|
|||
///
|
||||
/// Event sources registered with this `Registry` will be registered with
|
||||
/// the original `Registry` and `Poll` instance.
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub fn try_clone(&self) -> io::Result<Registry> {
|
||||
self.selector
|
||||
.try_clone()
|
||||
|
|
1
zeroidc/vendor/mio/src/sys/shell/selector.rs
vendored
1
zeroidc/vendor/mio/src/sys/shell/selector.rs
vendored
|
@ -11,7 +11,6 @@ pub type Events = Vec<Event>;
|
|||
pub struct Selector {}
|
||||
|
||||
impl Selector {
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub fn try_clone(&self) -> io::Result<Selector> {
|
||||
os_required!();
|
||||
}
|
||||
|
|
20
zeroidc/vendor/mio/src/sys/unix/pipe.rs
vendored
20
zeroidc/vendor/mio/src/sys/unix/pipe.rs
vendored
|
@ -313,29 +313,29 @@ impl event::Source for Sender {
|
|||
|
||||
impl Write for Sender {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).write(buf))
|
||||
self.inner.do_io(|mut sender| sender.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).write_vectored(bufs))
|
||||
self.inner.do_io(|mut sender| sender.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|sender| (&*sender).flush())
|
||||
self.inner.do_io(|mut sender| sender.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for &Sender {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).write(buf))
|
||||
self.inner.do_io(|mut sender| sender.write(buf))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).write_vectored(bufs))
|
||||
self.inner.do_io(|mut sender| sender.write_vectored(bufs))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.do_io(|sender| (&*sender).flush())
|
||||
self.inner.do_io(|mut sender| sender.flush())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,21 +478,21 @@ impl event::Source for Receiver {
|
|||
|
||||
impl Read for Receiver {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).read(buf))
|
||||
self.inner.do_io(|mut sender| sender.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).read_vectored(bufs))
|
||||
self.inner.do_io(|mut sender| sender.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for &Receiver {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).read(buf))
|
||||
self.inner.do_io(|mut sender| sender.read(buf))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.inner.do_io(|sender| (&*sender).read_vectored(bufs))
|
||||
self.inner.do_io(|mut sender| sender.read_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,41 @@ pub struct Selector {
|
|||
|
||||
impl Selector {
|
||||
pub fn new() -> io::Result<Selector> {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let res = syscall!(epoll_create1(libc::EPOLL_CLOEXEC));
|
||||
|
||||
// On Android < API level 16 `epoll_create1` is not defined, so use a
|
||||
// raw system call.
|
||||
// According to libuv, `EPOLL_CLOEXEC` is not defined on Android API <
|
||||
// 21. But `EPOLL_CLOEXEC` is an alias for `O_CLOEXEC` on that platform,
|
||||
// so we use it instead.
|
||||
#[cfg(target_os = "android")]
|
||||
let flag = libc::O_CLOEXEC;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let flag = libc::EPOLL_CLOEXEC;
|
||||
let res = syscall!(syscall(libc::SYS_epoll_create1, libc::O_CLOEXEC));
|
||||
|
||||
syscall!(epoll_create1(flag)).map(|ep| Selector {
|
||||
let ep = match res {
|
||||
Ok(ep) => ep as RawFd,
|
||||
Err(err) => {
|
||||
// When `epoll_create1` is not available fall back to use
|
||||
// `epoll_create` followed by `fcntl`.
|
||||
if let Some(libc::ENOSYS) = err.raw_os_error() {
|
||||
match syscall!(epoll_create(1024)) {
|
||||
Ok(ep) => match syscall!(fcntl(ep, libc::F_SETFD, libc::FD_CLOEXEC)) {
|
||||
Ok(ep) => ep as RawFd,
|
||||
Err(err) => {
|
||||
// `fcntl` failed, cleanup `ep`.
|
||||
let _ = unsafe { libc::close(ep) };
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
|
||||
ep,
|
||||
|
@ -61,7 +87,19 @@ impl Selector {
|
|||
const MAX_SAFE_TIMEOUT: u128 = libc::c_int::max_value() as u128;
|
||||
|
||||
let timeout = timeout
|
||||
.map(|to| cmp::min(to.as_millis(), MAX_SAFE_TIMEOUT) as libc::c_int)
|
||||
.map(|to| {
|
||||
let to_ms = to.as_millis();
|
||||
// as_millis() truncates, so round up to 1 ms as the documentation says can happen.
|
||||
// This avoids turning submillisecond timeouts into immediate returns unless the
|
||||
// caller explicitly requests that by specifying a zero timeout.
|
||||
let to_ms = to_ms
|
||||
+ if to_ms == 0 && to.subsec_nanos() != 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
cmp::min(MAX_SAFE_TIMEOUT, to_ms) as libc::c_int
|
||||
})
|
||||
.unwrap_or(-1);
|
||||
|
||||
events.clear();
|
||||
|
|
4
zeroidc/vendor/mio/src/sys/unix/uds/mod.rs
vendored
4
zeroidc/vendor/mio/src/sys/unix/uds/mod.rs
vendored
|
@ -40,7 +40,7 @@ cfg_os_poll! {
|
|||
sockaddr.sun_family = libc::AF_UNIX as libc::sa_family_t;
|
||||
|
||||
let bytes = path.as_os_str().as_bytes();
|
||||
match (bytes.get(0), bytes.len().cmp(&sockaddr.sun_path.len())) {
|
||||
match (bytes.first(), bytes.len().cmp(&sockaddr.sun_path.len())) {
|
||||
// Abstract paths don't need a null terminator
|
||||
(Some(&0), Ordering::Greater) => {
|
||||
return Err(io::Error::new(
|
||||
|
@ -64,7 +64,7 @@ cfg_os_poll! {
|
|||
let offset = path_offset(&sockaddr);
|
||||
let mut socklen = offset + bytes.len();
|
||||
|
||||
match bytes.get(0) {
|
||||
match bytes.first() {
|
||||
// The struct has already been zeroes so the null byte for pathname
|
||||
// addresses is already there.
|
||||
Some(&0) | None => {}
|
||||
|
|
14
zeroidc/vendor/mio/src/sys/wasi/mod.rs
vendored
14
zeroidc/vendor/mio/src/sys/wasi/mod.rs
vendored
|
@ -77,6 +77,12 @@ impl Selector {
|
|||
events.reserve(length);
|
||||
|
||||
debug_assert!(events.capacity() >= length);
|
||||
#[cfg(debug_assertions)]
|
||||
if length == 0 {
|
||||
log::warn!(
|
||||
"calling mio::Poll::poll with empty subscriptions, this likely not what you want"
|
||||
);
|
||||
}
|
||||
|
||||
let res = unsafe { wasi::poll_oneoff(subscriptions.as_ptr(), events.as_mut_ptr(), length) };
|
||||
|
||||
|
@ -110,6 +116,14 @@ impl Selector {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_clone(&self) -> io::Result<Selector> {
|
||||
Ok(Selector {
|
||||
#[cfg(all(debug_assertions, feature = "net"))]
|
||||
id: self.id,
|
||||
subscriptions: self.subscriptions.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) fn register(
|
||||
&self,
|
||||
|
|
12
zeroidc/vendor/mio/src/sys/windows/iocp.rs
vendored
12
zeroidc/vendor/mio/src/sys/windows/iocp.rs
vendored
|
@ -224,7 +224,17 @@ impl CompletionStatus {
|
|||
#[inline]
|
||||
fn duration_millis(dur: Option<Duration>) -> u32 {
|
||||
if let Some(dur) = dur {
|
||||
std::cmp::min(dur.as_millis(), u32::MAX as u128) as u32
|
||||
let dur_ms = dur.as_millis();
|
||||
// as_millis() truncates, so round nonzero <1ms timeouts up to 1ms. This avoids turning
|
||||
// submillisecond timeouts into immediate reutrns unless the caller explictly requests that
|
||||
// by specifiying a zero timeout.
|
||||
let dur_ms = dur_ms
|
||||
+ if dur_ms == 0 && dur.subsec_nanos() != 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
std::cmp::min(dur_ms, u32::MAX as u128) as u32
|
||||
} else {
|
||||
u32::MAX
|
||||
}
|
||||
|
|
2
zeroidc/vendor/tokio/.cargo-checksum.json
vendored
2
zeroidc/vendor/tokio/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
402
zeroidc/vendor/tokio/CHANGELOG.md
vendored
402
zeroidc/vendor/tokio/CHANGELOG.md
vendored
|
@ -1,3 +1,383 @@
|
|||
# 1.24.1 (January 6, 2022)
|
||||
|
||||
This release fixes a compilation failure on targets without `AtomicU64` when using rustc older than 1.63. ([#5356])
|
||||
|
||||
[#5356]: https://github.com/tokio-rs/tokio/pull/5356
|
||||
|
||||
# 1.24.0 (January 5, 2022)
|
||||
|
||||
### Fixed
|
||||
- rt: improve native `AtomicU64` support detection ([#5284])
|
||||
|
||||
### Added
|
||||
- rt: add configuration option for max number of I/O events polled from the OS
|
||||
per tick ([#5186])
|
||||
- rt: add an environment variable for configuring the default number of worker
|
||||
threads per runtime instance ([#4250])
|
||||
|
||||
### Changed
|
||||
- sync: reduce MPSC channel stack usage ([#5294])
|
||||
- io: reduce lock contention in I/O operations ([#5300])
|
||||
- fs: speed up `read_dir()` by chunking operations ([#5309])
|
||||
- rt: use internal `ThreadId` implementation ([#5329])
|
||||
- test: don't auto-advance time when a `spawn_blocking` task is running ([#5115])
|
||||
|
||||
[#5186]: https://github.com/tokio-rs/tokio/pull/5186
|
||||
[#5294]: https://github.com/tokio-rs/tokio/pull/5294
|
||||
[#5284]: https://github.com/tokio-rs/tokio/pull/5284
|
||||
[#4250]: https://github.com/tokio-rs/tokio/pull/4250
|
||||
[#5300]: https://github.com/tokio-rs/tokio/pull/5300
|
||||
[#5329]: https://github.com/tokio-rs/tokio/pull/5329
|
||||
[#5115]: https://github.com/tokio-rs/tokio/pull/5115
|
||||
[#5309]: https://github.com/tokio-rs/tokio/pull/5309
|
||||
|
||||
# 1.23.1 (January 4, 2022)
|
||||
|
||||
This release forward ports changes from 1.18.4.
|
||||
|
||||
### Fixed
|
||||
|
||||
- net: fix Windows named pipe server builder to maintain option when toggling
|
||||
pipe mode ([#5336]).
|
||||
|
||||
[#5336]: https://github.com/tokio-rs/tokio/pull/5336
|
||||
|
||||
# 1.23.0 (December 5, 2022)
|
||||
|
||||
### Fixed
|
||||
|
||||
- net: fix Windows named pipe connect ([#5208])
|
||||
- io: support vectored writes for `ChildStdin` ([#5216])
|
||||
- io: fix `async fn ready()` false positive for OS-specific events ([#5231])
|
||||
|
||||
### Changed
|
||||
- runtime: `yield_now` defers task until after driver poll ([#5223])
|
||||
- runtime: reduce amount of codegen needed per spawned task ([#5213])
|
||||
- windows: replace `winapi` dependency with `windows-sys` ([#5204])
|
||||
|
||||
[#5208]: https://github.com/tokio-rs/tokio/pull/5208
|
||||
[#5216]: https://github.com/tokio-rs/tokio/pull/5216
|
||||
[#5213]: https://github.com/tokio-rs/tokio/pull/5213
|
||||
[#5204]: https://github.com/tokio-rs/tokio/pull/5204
|
||||
[#5223]: https://github.com/tokio-rs/tokio/pull/5223
|
||||
[#5231]: https://github.com/tokio-rs/tokio/pull/5231
|
||||
|
||||
# 1.22.0 (November 17, 2022)
|
||||
|
||||
### Added
|
||||
- runtime: add `Handle::runtime_flavor` ([#5138])
|
||||
- sync: add `Mutex::blocking_lock_owned` ([#5130])
|
||||
- sync: add `Semaphore::MAX_PERMITS` ([#5144])
|
||||
- sync: add `merge()` to semaphore permits ([#4948])
|
||||
- sync: add `mpsc::WeakUnboundedSender` ([#5189])
|
||||
|
||||
### Added (unstable)
|
||||
|
||||
- process: add `Command::process_group` ([#5114])
|
||||
- runtime: export metrics about the blocking thread pool ([#5161])
|
||||
- task: add `task::id()` and `task::try_id()` ([#5171])
|
||||
|
||||
### Fixed
|
||||
- macros: don't take ownership of futures in macros ([#5087])
|
||||
- runtime: fix Stacked Borrows violation in `LocalOwnedTasks` ([#5099])
|
||||
- runtime: mitigate ABA with 32-bit queue indices when possible ([#5042])
|
||||
- task: wake local tasks to the local queue when woken by the same thread ([#5095])
|
||||
- time: panic in release mode when `mark_pending` called illegally ([#5093])
|
||||
- runtime: fix typo in expect message ([#5169])
|
||||
- runtime: fix `unsync_load` on atomic types ([#5175])
|
||||
- task: elaborate safety comments in task deallocation ([#5172])
|
||||
- runtime: fix `LocalSet` drop in thread local ([#5179])
|
||||
- net: remove libc type leakage in a public API ([#5191])
|
||||
- runtime: update the alignment of `CachePadded` ([#5106])
|
||||
|
||||
### Changed
|
||||
- io: make `tokio::io::copy` continue filling the buffer when writer stalls ([#5066])
|
||||
- runtime: remove `coop::budget` from `LocalSet::run_until` ([#5155])
|
||||
- sync: make `Notify` panic safe ([#5154])
|
||||
|
||||
### Documented
|
||||
- io: fix doc for `write_i8` to use signed integers ([#5040])
|
||||
- net: fix doc typos for TCP and UDP `set_tos` methods ([#5073])
|
||||
- net: fix function name in `UdpSocket::recv` documentation ([#5150])
|
||||
- sync: typo in `TryLockError` for `RwLock::try_write` ([#5160])
|
||||
- task: document that spawned tasks execute immediately ([#5117])
|
||||
- time: document return type of `timeout` ([#5118])
|
||||
- time: document that `timeout` checks only before poll ([#5126])
|
||||
- sync: specify return type of `oneshot::Receiver` in docs ([#5198])
|
||||
|
||||
### Internal changes
|
||||
- runtime: use const `Mutex::new` for globals ([#5061])
|
||||
- runtime: remove `Option` around `mio::Events` in io driver ([#5078])
|
||||
- runtime: remove a conditional compilation clause ([#5104])
|
||||
- runtime: remove a reference to internal time handle ([#5107])
|
||||
- runtime: misc time driver cleanup ([#5120])
|
||||
- runtime: move signal driver to runtime module ([#5121])
|
||||
- runtime: signal driver now uses I/O driver directly ([#5125])
|
||||
- runtime: start decoupling I/O driver and I/O handle ([#5127])
|
||||
- runtime: switch `io::handle` refs with scheduler:Handle ([#5128])
|
||||
- runtime: remove Arc from I/O driver ([#5134])
|
||||
- runtime: use signal driver handle via `scheduler::Handle` ([#5135])
|
||||
- runtime: move internal clock fns out of context ([#5139])
|
||||
- runtime: remove `runtime::context` module ([#5140])
|
||||
- runtime: keep driver cfgs in `driver.rs` ([#5141])
|
||||
- runtime: add `runtime::context` to unify thread-locals ([#5143])
|
||||
- runtime: rename some confusing internal variables/fns ([#5151])
|
||||
- runtime: move `coop` mod into `runtime` ([#5152])
|
||||
- runtime: move budget state to context thread-local ([#5157])
|
||||
- runtime: move park logic into runtime module ([#5158])
|
||||
- runtime: move `Runtime` into its own file ([#5159])
|
||||
- runtime: unify entering a runtime with `Handle::enter` ([#5163])
|
||||
- runtime: remove handle reference from each scheduler ([#5166])
|
||||
- runtime: move `enter` into `context` ([#5167])
|
||||
- runtime: combine context and entered thread-locals ([#5168])
|
||||
- runtime: fix accidental unsetting of current handle ([#5178])
|
||||
- runtime: move `CoreStage` methods to `Core` ([#5182])
|
||||
- sync: name mpsc semaphore types ([#5146])
|
||||
|
||||
[#4948]: https://github.com/tokio-rs/tokio/pull/4948
|
||||
[#5040]: https://github.com/tokio-rs/tokio/pull/5040
|
||||
[#5042]: https://github.com/tokio-rs/tokio/pull/5042
|
||||
[#5061]: https://github.com/tokio-rs/tokio/pull/5061
|
||||
[#5066]: https://github.com/tokio-rs/tokio/pull/5066
|
||||
[#5073]: https://github.com/tokio-rs/tokio/pull/5073
|
||||
[#5078]: https://github.com/tokio-rs/tokio/pull/5078
|
||||
[#5087]: https://github.com/tokio-rs/tokio/pull/5087
|
||||
[#5093]: https://github.com/tokio-rs/tokio/pull/5093
|
||||
[#5095]: https://github.com/tokio-rs/tokio/pull/5095
|
||||
[#5099]: https://github.com/tokio-rs/tokio/pull/5099
|
||||
[#5104]: https://github.com/tokio-rs/tokio/pull/5104
|
||||
[#5106]: https://github.com/tokio-rs/tokio/pull/5106
|
||||
[#5107]: https://github.com/tokio-rs/tokio/pull/5107
|
||||
[#5114]: https://github.com/tokio-rs/tokio/pull/5114
|
||||
[#5117]: https://github.com/tokio-rs/tokio/pull/5117
|
||||
[#5118]: https://github.com/tokio-rs/tokio/pull/5118
|
||||
[#5120]: https://github.com/tokio-rs/tokio/pull/5120
|
||||
[#5121]: https://github.com/tokio-rs/tokio/pull/5121
|
||||
[#5125]: https://github.com/tokio-rs/tokio/pull/5125
|
||||
[#5126]: https://github.com/tokio-rs/tokio/pull/5126
|
||||
[#5127]: https://github.com/tokio-rs/tokio/pull/5127
|
||||
[#5128]: https://github.com/tokio-rs/tokio/pull/5128
|
||||
[#5130]: https://github.com/tokio-rs/tokio/pull/5130
|
||||
[#5134]: https://github.com/tokio-rs/tokio/pull/5134
|
||||
[#5135]: https://github.com/tokio-rs/tokio/pull/5135
|
||||
[#5138]: https://github.com/tokio-rs/tokio/pull/5138
|
||||
[#5138]: https://github.com/tokio-rs/tokio/pull/5138
|
||||
[#5139]: https://github.com/tokio-rs/tokio/pull/5139
|
||||
[#5140]: https://github.com/tokio-rs/tokio/pull/5140
|
||||
[#5141]: https://github.com/tokio-rs/tokio/pull/5141
|
||||
[#5143]: https://github.com/tokio-rs/tokio/pull/5143
|
||||
[#5144]: https://github.com/tokio-rs/tokio/pull/5144
|
||||
[#5144]: https://github.com/tokio-rs/tokio/pull/5144
|
||||
[#5146]: https://github.com/tokio-rs/tokio/pull/5146
|
||||
[#5150]: https://github.com/tokio-rs/tokio/pull/5150
|
||||
[#5151]: https://github.com/tokio-rs/tokio/pull/5151
|
||||
[#5152]: https://github.com/tokio-rs/tokio/pull/5152
|
||||
[#5154]: https://github.com/tokio-rs/tokio/pull/5154
|
||||
[#5155]: https://github.com/tokio-rs/tokio/pull/5155
|
||||
[#5157]: https://github.com/tokio-rs/tokio/pull/5157
|
||||
[#5158]: https://github.com/tokio-rs/tokio/pull/5158
|
||||
[#5159]: https://github.com/tokio-rs/tokio/pull/5159
|
||||
[#5160]: https://github.com/tokio-rs/tokio/pull/5160
|
||||
[#5161]: https://github.com/tokio-rs/tokio/pull/5161
|
||||
[#5163]: https://github.com/tokio-rs/tokio/pull/5163
|
||||
[#5166]: https://github.com/tokio-rs/tokio/pull/5166
|
||||
[#5167]: https://github.com/tokio-rs/tokio/pull/5167
|
||||
[#5168]: https://github.com/tokio-rs/tokio/pull/5168
|
||||
[#5169]: https://github.com/tokio-rs/tokio/pull/5169
|
||||
[#5171]: https://github.com/tokio-rs/tokio/pull/5171
|
||||
[#5172]: https://github.com/tokio-rs/tokio/pull/5172
|
||||
[#5175]: https://github.com/tokio-rs/tokio/pull/5175
|
||||
[#5178]: https://github.com/tokio-rs/tokio/pull/5178
|
||||
[#5179]: https://github.com/tokio-rs/tokio/pull/5179
|
||||
[#5182]: https://github.com/tokio-rs/tokio/pull/5182
|
||||
[#5189]: https://github.com/tokio-rs/tokio/pull/5189
|
||||
[#5191]: https://github.com/tokio-rs/tokio/pull/5191
|
||||
[#5198]: https://github.com/tokio-rs/tokio/pull/5198
|
||||
|
||||
# 1.21.2 (September 27, 2022)
|
||||
|
||||
This release removes the dependency on the `once_cell` crate to restore the MSRV
|
||||
of 1.21.x, which is the latest minor version at the time of release. ([#5048])
|
||||
|
||||
[#5048]: https://github.com/tokio-rs/tokio/pull/5048
|
||||
|
||||
# 1.21.1 (September 13, 2022)
|
||||
|
||||
### Fixed
|
||||
|
||||
- net: fix dependency resolution for socket2 ([#5000])
|
||||
- task: ignore failure to set TLS in `LocalSet` Drop ([#4976])
|
||||
|
||||
[#4976]: https://github.com/tokio-rs/tokio/pull/4976
|
||||
[#5000]: https://github.com/tokio-rs/tokio/pull/5000
|
||||
|
||||
# 1.21.0 (September 2, 2022)
|
||||
|
||||
This release is the first release of Tokio to intentionally support WASM. The
|
||||
`sync,macros,io-util,rt,time` features are stabilized on WASM. Additionally the
|
||||
wasm32-wasi target is given unstable support for the `net` feature.
|
||||
|
||||
### Added
|
||||
|
||||
- net: add `device` and `bind_device` methods to TCP/UDP sockets ([#4882])
|
||||
- net: add `tos` and `set_tos` methods to TCP and UDP sockets ([#4877])
|
||||
- net: add security flags to named pipe `ServerOptions` ([#4845])
|
||||
- signal: add more windows signal handlers ([#4924])
|
||||
- sync: add `mpsc::Sender::max_capacity` method ([#4904])
|
||||
- sync: implement Weak version of `mpsc::Sender` ([#4595])
|
||||
- task: add `LocalSet::enter` ([#4765])
|
||||
- task: stabilize `JoinSet` and `AbortHandle` ([#4920])
|
||||
- tokio: add `track_caller` to public APIs ([#4805], [#4848], [#4852])
|
||||
- wasm: initial support for `wasm32-wasi` target ([#4716])
|
||||
|
||||
### Fixed
|
||||
|
||||
- miri: improve miri compatibility by avoiding temporary references in `linked_list::Link` impls ([#4841])
|
||||
- signal: don't register write interest on signal pipe ([#4898])
|
||||
- sync: add `#[must_use]` to lock guards ([#4886])
|
||||
- sync: fix hang when calling `recv` on closed and reopened broadcast channel ([#4867])
|
||||
- task: propagate attributes on task-locals ([#4837])
|
||||
|
||||
### Changed
|
||||
|
||||
- fs: change panic to error in `File::start_seek` ([#4897])
|
||||
- io: reduce syscalls in `poll_read` ([#4840])
|
||||
- process: use blocking threadpool for child stdio I/O ([#4824])
|
||||
- signal: make `SignalKind` methods const ([#4956])
|
||||
|
||||
### Internal changes
|
||||
|
||||
- rt: extract `basic_scheduler::Config` ([#4935])
|
||||
- rt: move I/O driver into `runtime` module ([#4942])
|
||||
- rt: rename internal scheduler types ([#4945])
|
||||
|
||||
### Documented
|
||||
|
||||
- chore: fix typos and grammar ([#4858], [#4894], [#4928])
|
||||
- io: fix typo in `AsyncSeekExt::rewind` docs ([#4893])
|
||||
- net: add documentation to `try_read()` for zero-length buffers ([#4937])
|
||||
- runtime: remove incorrect panic section for `Builder::worker_threads` ([#4849])
|
||||
- sync: doc of `watch::Sender::send` improved ([#4959])
|
||||
- task: add cancel safety docs to `JoinHandle` ([#4901])
|
||||
- task: expand on cancellation of `spawn_blocking` ([#4811])
|
||||
- time: clarify that the first tick of `Interval::tick` happens immediately ([#4951])
|
||||
|
||||
### Unstable
|
||||
|
||||
- rt: add unstable option to disable the LIFO slot ([#4936])
|
||||
- task: fix incorrect signature in `Builder::spawn_on` ([#4953])
|
||||
- task: make `task::Builder::spawn*` methods fallible ([#4823])
|
||||
|
||||
[#4595]: https://github.com/tokio-rs/tokio/pull/4595
|
||||
[#4716]: https://github.com/tokio-rs/tokio/pull/4716
|
||||
[#4765]: https://github.com/tokio-rs/tokio/pull/4765
|
||||
[#4805]: https://github.com/tokio-rs/tokio/pull/4805
|
||||
[#4811]: https://github.com/tokio-rs/tokio/pull/4811
|
||||
[#4823]: https://github.com/tokio-rs/tokio/pull/4823
|
||||
[#4824]: https://github.com/tokio-rs/tokio/pull/4824
|
||||
[#4837]: https://github.com/tokio-rs/tokio/pull/4837
|
||||
[#4840]: https://github.com/tokio-rs/tokio/pull/4840
|
||||
[#4841]: https://github.com/tokio-rs/tokio/pull/4841
|
||||
[#4845]: https://github.com/tokio-rs/tokio/pull/4845
|
||||
[#4848]: https://github.com/tokio-rs/tokio/pull/4848
|
||||
[#4849]: https://github.com/tokio-rs/tokio/pull/4849
|
||||
[#4852]: https://github.com/tokio-rs/tokio/pull/4852
|
||||
[#4858]: https://github.com/tokio-rs/tokio/pull/4858
|
||||
[#4867]: https://github.com/tokio-rs/tokio/pull/4867
|
||||
[#4877]: https://github.com/tokio-rs/tokio/pull/4877
|
||||
[#4882]: https://github.com/tokio-rs/tokio/pull/4882
|
||||
[#4886]: https://github.com/tokio-rs/tokio/pull/4886
|
||||
[#4893]: https://github.com/tokio-rs/tokio/pull/4893
|
||||
[#4894]: https://github.com/tokio-rs/tokio/pull/4894
|
||||
[#4897]: https://github.com/tokio-rs/tokio/pull/4897
|
||||
[#4898]: https://github.com/tokio-rs/tokio/pull/4898
|
||||
[#4901]: https://github.com/tokio-rs/tokio/pull/4901
|
||||
[#4904]: https://github.com/tokio-rs/tokio/pull/4904
|
||||
[#4920]: https://github.com/tokio-rs/tokio/pull/4920
|
||||
[#4924]: https://github.com/tokio-rs/tokio/pull/4924
|
||||
[#4928]: https://github.com/tokio-rs/tokio/pull/4928
|
||||
[#4935]: https://github.com/tokio-rs/tokio/pull/4935
|
||||
[#4936]: https://github.com/tokio-rs/tokio/pull/4936
|
||||
[#4937]: https://github.com/tokio-rs/tokio/pull/4937
|
||||
[#4942]: https://github.com/tokio-rs/tokio/pull/4942
|
||||
[#4945]: https://github.com/tokio-rs/tokio/pull/4945
|
||||
[#4951]: https://github.com/tokio-rs/tokio/pull/4951
|
||||
[#4953]: https://github.com/tokio-rs/tokio/pull/4953
|
||||
[#4956]: https://github.com/tokio-rs/tokio/pull/4956
|
||||
[#4959]: https://github.com/tokio-rs/tokio/pull/4959
|
||||
|
||||
# 1.20.3 (January 3, 2022)
|
||||
|
||||
This release forward ports changes from 1.18.4.
|
||||
|
||||
### Fixed
|
||||
|
||||
- net: fix Windows named pipe server builder to maintain option when toggling
|
||||
pipe mode ([#5336]).
|
||||
|
||||
[#5336]: https://github.com/tokio-rs/tokio/pull/5336
|
||||
|
||||
# 1.20.2 (September 27, 2022)
|
||||
|
||||
This release removes the dependency on the `once_cell` crate to restore the MSRV
|
||||
of the 1.20.x LTS release. ([#5048])
|
||||
|
||||
[#5048]: https://github.com/tokio-rs/tokio/pull/5048
|
||||
|
||||
# 1.20.1 (July 25, 2022)
|
||||
|
||||
### Fixed
|
||||
|
||||
- chore: fix version detection in build script ([#4860])
|
||||
|
||||
[#4860]: https://github.com/tokio-rs/tokio/pull/4860
|
||||
|
||||
# 1.20.0 (July 12, 2022)
|
||||
|
||||
### Added
|
||||
- tokio: add `track_caller` to public APIs ([#4772], [#4791], [#4793], [#4806], [#4808])
|
||||
- sync: Add `has_changed` method to `watch::Ref` ([#4758])
|
||||
|
||||
### Changed
|
||||
|
||||
- time: remove `src/time/driver/wheel/stack.rs` ([#4766])
|
||||
- rt: clean up arguments passed to basic scheduler ([#4767])
|
||||
- net: be more specific about winapi features ([#4764])
|
||||
- tokio: use const initialized thread locals where possible ([#4677])
|
||||
- task: various small improvements to LocalKey ([#4795])
|
||||
|
||||
### Documented
|
||||
|
||||
- fs: warn about performance pitfall ([#4762])
|
||||
- chore: fix spelling ([#4769])
|
||||
- sync: document spurious failures in oneshot ([#4777])
|
||||
- sync: add warning for watch in non-Send futures ([#4741])
|
||||
- chore: fix typo ([#4798])
|
||||
|
||||
### Unstable
|
||||
|
||||
- joinset: rename `join_one` to `join_next` ([#4755])
|
||||
- rt: unhandled panic config for current thread rt ([#4770])
|
||||
|
||||
[#4677]: https://github.com/tokio-rs/tokio/pull/4677
|
||||
[#4741]: https://github.com/tokio-rs/tokio/pull/4741
|
||||
[#4755]: https://github.com/tokio-rs/tokio/pull/4755
|
||||
[#4758]: https://github.com/tokio-rs/tokio/pull/4758
|
||||
[#4762]: https://github.com/tokio-rs/tokio/pull/4762
|
||||
[#4764]: https://github.com/tokio-rs/tokio/pull/4764
|
||||
[#4766]: https://github.com/tokio-rs/tokio/pull/4766
|
||||
[#4767]: https://github.com/tokio-rs/tokio/pull/4767
|
||||
[#4769]: https://github.com/tokio-rs/tokio/pull/4769
|
||||
[#4770]: https://github.com/tokio-rs/tokio/pull/4770
|
||||
[#4772]: https://github.com/tokio-rs/tokio/pull/4772
|
||||
[#4777]: https://github.com/tokio-rs/tokio/pull/4777
|
||||
[#4791]: https://github.com/tokio-rs/tokio/pull/4791
|
||||
[#4793]: https://github.com/tokio-rs/tokio/pull/4793
|
||||
[#4795]: https://github.com/tokio-rs/tokio/pull/4795
|
||||
[#4798]: https://github.com/tokio-rs/tokio/pull/4798
|
||||
[#4806]: https://github.com/tokio-rs/tokio/pull/4806
|
||||
[#4808]: https://github.com/tokio-rs/tokio/pull/4808
|
||||
|
||||
# 1.19.2 (June 6, 2022)
|
||||
|
||||
This release fixes another bug in `Notified::enable`. ([#4751])
|
||||
|
@ -62,6 +442,22 @@ This release fixes a bug in `Notified::enable`. ([#4747])
|
|||
[#4729]: https://github.com/tokio-rs/tokio/pull/4729
|
||||
[#4739]: https://github.com/tokio-rs/tokio/pull/4739
|
||||
|
||||
# 1.18.4 (January 3, 2022)
|
||||
|
||||
### Fixed
|
||||
|
||||
- net: fix Windows named pipe server builder to maintain option when toggling
|
||||
pipe mode ([#5336]).
|
||||
|
||||
[#5336]: https://github.com/tokio-rs/tokio/pull/5336
|
||||
|
||||
# 1.18.3 (September 27, 2022)
|
||||
|
||||
This release removes the dependency on the `once_cell` crate to restore the MSRV
|
||||
of the 1.18.x LTS release. ([#5048])
|
||||
|
||||
[#5048]: https://github.com/tokio-rs/tokio/pull/5048
|
||||
|
||||
# 1.18.2 (May 5, 2022)
|
||||
|
||||
Add missing features for the `winapi` dependency. ([#4663])
|
||||
|
@ -1235,7 +1631,7 @@ Biggest changes are:
|
|||
- Feature flags are simplified
|
||||
- `rt-core` and `rt-util` are combined to `rt`
|
||||
- `rt-threaded` is renamed to `rt-multi-thread` to match builder API
|
||||
- `tcp`, `udp`, `uds`, `dns` are combied to `net`.
|
||||
- `tcp`, `udp`, `uds`, `dns` are combined to `net`.
|
||||
- `parking_lot` is included with `full`
|
||||
|
||||
### Changes
|
||||
|
@ -1733,7 +2129,7 @@ Biggest changes are:
|
|||
- `net::lookup_host` maps a `T: ToSocketAddrs` to a stream of `SocketAddrs` ([#1870]).
|
||||
- `process::Child` fields are made public to match `std` ([#2014]).
|
||||
- impl `Stream` for `sync::broadcast::Receiver` ([#2012]).
|
||||
- `sync::RwLock` provides an asynchonous read-write lock ([#1699]).
|
||||
- `sync::RwLock` provides an asynchronous read-write lock ([#1699]).
|
||||
- `runtime::Handle::current` returns the handle for the current runtime ([#2040]).
|
||||
- `StreamExt::filter` filters stream values according to a predicate ([#2001]).
|
||||
- `StreamExt::filter_map` simultaneously filter and map stream values ([#2001]).
|
||||
|
@ -1842,7 +2238,7 @@ Biggest changes are:
|
|||
### Fixes
|
||||
|
||||
- calling `spawn_blocking` after runtime shutdown ([#1875]).
|
||||
- `LocalSet` drop inifinite loop ([#1892]).
|
||||
- `LocalSet` drop infinite loop ([#1892]).
|
||||
- `LocalSet` hang under load ([#1905]).
|
||||
- improved documentation ([#1865], [#1866], [#1868], [#1874], [#1876], [#1911]).
|
||||
|
||||
|
|
76
zeroidc/vendor/tokio/Cargo.toml
vendored
76
zeroidc/vendor/tokio/Cargo.toml
vendored
|
@ -13,7 +13,7 @@
|
|||
edition = "2018"
|
||||
rust-version = "1.49"
|
||||
name = "tokio"
|
||||
version = "1.19.2"
|
||||
version = "1.24.1"
|
||||
authors = ["Tokio Contributors <team@tokio.rs>"]
|
||||
description = """
|
||||
An event-driven, non-blocking I/O platform for writing asynchronous I/O
|
||||
|
@ -62,17 +62,13 @@ version = "2.2"
|
|||
optional = true
|
||||
|
||||
[dependencies.mio]
|
||||
version = "0.8.1"
|
||||
version = "0.8.4"
|
||||
optional = true
|
||||
|
||||
[dependencies.num_cpus]
|
||||
version = "1.8.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.5.2"
|
||||
optional = true
|
||||
|
||||
[dependencies.parking_lot]
|
||||
version = "0.12.0"
|
||||
optional = true
|
||||
|
@ -80,11 +76,6 @@ optional = true
|
|||
[dependencies.pin-project-lite]
|
||||
version = "0.2.0"
|
||||
|
||||
[dependencies.socket2]
|
||||
version = "0.4.4"
|
||||
features = ["all"]
|
||||
optional = true
|
||||
|
||||
[dependencies.tokio-macros]
|
||||
version = "1.7.0"
|
||||
optional = true
|
||||
|
@ -108,6 +99,9 @@ version = "0.1"
|
|||
[dev-dependencies.tokio-test]
|
||||
version = "0.4.0"
|
||||
|
||||
[build-dependencies.autocfg]
|
||||
version = "1.1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
fs = []
|
||||
|
@ -137,31 +131,36 @@ net = [
|
|||
"mio/os-ext",
|
||||
"mio/net",
|
||||
"socket2",
|
||||
"winapi/namedpipeapi",
|
||||
"windows-sys/Win32_Foundation",
|
||||
"windows-sys/Win32_Security",
|
||||
"windows-sys/Win32_Storage_FileSystem",
|
||||
"windows-sys/Win32_System_Pipes",
|
||||
"windows-sys/Win32_System_SystemServices",
|
||||
]
|
||||
process = [
|
||||
"bytes",
|
||||
"once_cell",
|
||||
"libc",
|
||||
"mio/os-poll",
|
||||
"mio/os-ext",
|
||||
"mio/net",
|
||||
"signal-hook-registry",
|
||||
"winapi/threadpoollegacyapiset",
|
||||
"windows-sys/Win32_Foundation",
|
||||
"windows-sys/Win32_System_Threading",
|
||||
"windows-sys/Win32_System_WindowsProgramming",
|
||||
]
|
||||
rt = ["once_cell"]
|
||||
rt = []
|
||||
rt-multi-thread = [
|
||||
"num_cpus",
|
||||
"rt",
|
||||
]
|
||||
signal = [
|
||||
"once_cell",
|
||||
"libc",
|
||||
"mio/os-poll",
|
||||
"mio/net",
|
||||
"mio/os-ext",
|
||||
"signal-hook-registry",
|
||||
"winapi/consoleapi",
|
||||
"windows-sys/Win32_Foundation",
|
||||
"windows-sys/Win32_System_Console",
|
||||
]
|
||||
stats = []
|
||||
sync = []
|
||||
|
@ -172,6 +171,16 @@ test-util = [
|
|||
]
|
||||
time = []
|
||||
|
||||
[target."cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), not(target_os = \"wasi\")))".dev-dependencies.wasm-bindgen-test]
|
||||
version = "0.3.0"
|
||||
|
||||
[target."cfg(docsrs)".dependencies.windows-sys]
|
||||
version = "0.42.0"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Security_Authorization",
|
||||
]
|
||||
|
||||
[target."cfg(loom)".dev-dependencies.loom]
|
||||
version = "0.5.2"
|
||||
features = [
|
||||
|
@ -179,20 +188,22 @@ features = [
|
|||
"checkpoint",
|
||||
]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dev-dependencies.proptest]
|
||||
version = "1"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dev-dependencies.rand]
|
||||
[target."cfg(not(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\")))".dev-dependencies.rand]
|
||||
version = "0.8.0"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dev-dependencies.socket2]
|
||||
[target."cfg(not(any(target_arch = \"wasm32\", target_arch = \"wasm64\")))".dependencies.socket2]
|
||||
version = "0.4.4"
|
||||
features = ["all"]
|
||||
optional = true
|
||||
|
||||
[target."cfg(not(any(target_arch = \"wasm32\", target_arch = \"wasm64\")))".dev-dependencies.proptest]
|
||||
version = "1"
|
||||
|
||||
[target."cfg(not(any(target_arch = \"wasm32\", target_arch = \"wasm64\")))".dev-dependencies.socket2]
|
||||
version = "0.4"
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test]
|
||||
version = "0.3.0"
|
||||
|
||||
[target."cfg(target_os = \"freebsd\")".dev-dependencies.mio-aio]
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
features = ["tokio"]
|
||||
|
||||
[target."cfg(tokio_unstable)".dependencies.tracing]
|
||||
|
@ -220,18 +231,9 @@ features = [
|
|||
]
|
||||
default-features = false
|
||||
|
||||
[target."cfg(windows)".dependencies.winapi]
|
||||
version = "0.3.8"
|
||||
features = [
|
||||
"std",
|
||||
"winsock2",
|
||||
"mswsock",
|
||||
"handleapi",
|
||||
"ws2ipdef",
|
||||
"ws2tcpip",
|
||||
]
|
||||
[target."cfg(windows)".dependencies.windows-sys]
|
||||
version = "0.42.0"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[target."cfg(windows)".dev-dependencies.ntapi]
|
||||
version = "0.3.6"
|
||||
|
|
26
zeroidc/vendor/tokio/README.md
vendored
26
zeroidc/vendor/tokio/README.md
vendored
|
@ -56,7 +56,7 @@ Make sure you activated the full features of the tokio crate on Cargo.toml:
|
|||
|
||||
```toml
|
||||
[dependencies]
|
||||
tokio = { version = "1.19.2", features = ["full"] }
|
||||
tokio = { version = "1.24.1", features = ["full"] }
|
||||
```
|
||||
Then, on your main.rs:
|
||||
|
||||
|
@ -161,6 +161,16 @@ several other libraries, including:
|
|||
[`mio`]: https://github.com/tokio-rs/mio
|
||||
[`bytes`]: https://github.com/tokio-rs/bytes
|
||||
|
||||
## Changelog
|
||||
|
||||
The Tokio repository contains multiple crates. Each crate has its own changelog.
|
||||
|
||||
* `tokio` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio/CHANGELOG.md)
|
||||
* `tokio-util` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-util/CHANGELOG.md)
|
||||
* `tokio-stream` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-stream/CHANGELOG.md)
|
||||
* `tokio-macros` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-macros/CHANGELOG.md)
|
||||
* `tokio-test` - [view changelog](https://github.com/tokio-rs/tokio/blob/master/tokio-test/CHANGELOG.md)
|
||||
|
||||
## Supported Rust Versions
|
||||
|
||||
<!--
|
||||
|
@ -192,18 +202,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.14.x` - LTS release until June 2022.
|
||||
* `1.18.x` - LTS release until January 2023
|
||||
* `1.18.x` - LTS release until June 2023
|
||||
* `1.20.x` - LTS release until September 2023.
|
||||
|
||||
Each LTS release will continue to receive backported fixes for at least half a
|
||||
year. If you wish to use a fixed minor release in your project, we recommend
|
||||
that you use an LTS release.
|
||||
Each LTS release will continue to receive backported fixes for at least a year.
|
||||
If you wish to use a fixed minor release in your project, we recommend that you
|
||||
use an LTS release.
|
||||
|
||||
To use a fixed minor version, you can specify the version with a tilde. For
|
||||
example, to specify that you wish to use the newest `1.14.x` patch release, you
|
||||
example, to specify that you wish to use the newest `1.18.x` patch release, you
|
||||
can use the following dependency specification:
|
||||
```text
|
||||
tokio = { version = "~1.14", features = [...] }
|
||||
tokio = { version = "~1.18", features = [...] }
|
||||
```
|
||||
|
||||
## License
|
||||
|
|
184
zeroidc/vendor/tokio/build.rs
vendored
Normal file
184
zeroidc/vendor/tokio/build.rs
vendored
Normal file
|
@ -0,0 +1,184 @@
|
|||
use autocfg::AutoCfg;
|
||||
|
||||
const CONST_THREAD_LOCAL_PROBE: &str = r#"
|
||||
{
|
||||
thread_local! {
|
||||
static MY_PROBE: usize = const { 10 };
|
||||
}
|
||||
|
||||
MY_PROBE.with(|val| *val)
|
||||
}
|
||||
"#;
|
||||
|
||||
const ADDR_OF_PROBE: &str = r#"
|
||||
{
|
||||
let my_var = 10;
|
||||
::std::ptr::addr_of!(my_var)
|
||||
}
|
||||
"#;
|
||||
|
||||
const CONST_MUTEX_NEW_PROBE: &str = r#"
|
||||
{
|
||||
static MY_MUTEX: ::std::sync::Mutex<i32> = ::std::sync::Mutex::new(1);
|
||||
*MY_MUTEX.lock().unwrap()
|
||||
}
|
||||
"#;
|
||||
|
||||
const TARGET_HAS_ATOMIC_PROBE: &str = r#"
|
||||
{
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
let _ = ();
|
||||
}
|
||||
"#;
|
||||
|
||||
const TARGET_ATOMIC_U64_PROBE: &str = r#"
|
||||
{
|
||||
use std::sync::atomic::AtomicU64 as _;
|
||||
}
|
||||
"#;
|
||||
|
||||
fn main() {
|
||||
let mut enable_const_thread_local = false;
|
||||
let mut enable_addr_of = false;
|
||||
let mut enable_target_has_atomic = false;
|
||||
let mut enable_const_mutex_new = false;
|
||||
let mut target_needs_atomic_u64_fallback = false;
|
||||
|
||||
match AutoCfg::new() {
|
||||
Ok(ac) => {
|
||||
// These checks prefer to call only `probe_rustc_version` if that is
|
||||
// enough to determine whether the feature is supported. This is
|
||||
// because the `probe_expression` call involves a call to rustc,
|
||||
// which the `probe_rustc_version` call avoids.
|
||||
|
||||
// Const-initialized thread locals were stabilized in 1.59.
|
||||
if ac.probe_rustc_version(1, 60) {
|
||||
enable_const_thread_local = true;
|
||||
} else if ac.probe_rustc_version(1, 59) {
|
||||
// This compiler claims to be 1.59, but there are some nightly
|
||||
// compilers that claim to be 1.59 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2021-12-06.
|
||||
if ac.probe_expression(CONST_THREAD_LOCAL_PROBE) {
|
||||
enable_const_thread_local = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The `addr_of` and `addr_of_mut` macros were stabilized in 1.51.
|
||||
if ac.probe_rustc_version(1, 52) {
|
||||
enable_addr_of = true;
|
||||
} else if ac.probe_rustc_version(1, 51) {
|
||||
// This compiler claims to be 1.51, but there are some nightly
|
||||
// compilers that claim to be 1.51 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2021-01-31.
|
||||
if ac.probe_expression(ADDR_OF_PROBE) {
|
||||
enable_addr_of = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The `target_has_atomic` cfg was stabilized in 1.60.
|
||||
if ac.probe_rustc_version(1, 61) {
|
||||
enable_target_has_atomic = true;
|
||||
} else if ac.probe_rustc_version(1, 60) {
|
||||
// This compiler claims to be 1.60, but there are some nightly
|
||||
// compilers that claim to be 1.60 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2022-02-11.
|
||||
if ac.probe_expression(TARGET_HAS_ATOMIC_PROBE) {
|
||||
enable_target_has_atomic = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't tell using `target_has_atomic`, tell if the target
|
||||
// has `AtomicU64` by trying to use it.
|
||||
if !enable_target_has_atomic && !ac.probe_expression(TARGET_ATOMIC_U64_PROBE) {
|
||||
target_needs_atomic_u64_fallback = true;
|
||||
}
|
||||
|
||||
// The `Mutex::new` method was made const in 1.63.
|
||||
if ac.probe_rustc_version(1, 64) {
|
||||
enable_const_mutex_new = true;
|
||||
} else if ac.probe_rustc_version(1, 63) {
|
||||
// This compiler claims to be 1.63, but there are some nightly
|
||||
// compilers that claim to be 1.63 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2022-06-20.
|
||||
if ac.probe_expression(CONST_MUTEX_NEW_PROBE) {
|
||||
enable_const_mutex_new = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
// If we couldn't detect the compiler version and features, just
|
||||
// print a warning. This isn't a fatal error: we can still build
|
||||
// Tokio, we just can't enable cfgs automatically.
|
||||
println!(
|
||||
"cargo:warning=tokio: failed to detect compiler features: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if !enable_const_thread_local {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_const_thread_local"
|
||||
autocfg::emit("tokio_no_const_thread_local")
|
||||
}
|
||||
|
||||
if !enable_addr_of {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_addr_of"
|
||||
autocfg::emit("tokio_no_addr_of")
|
||||
}
|
||||
|
||||
if !enable_target_has_atomic {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_target_has_atomic"
|
||||
autocfg::emit("tokio_no_target_has_atomic")
|
||||
}
|
||||
|
||||
if !enable_const_mutex_new {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_const_mutex_new"
|
||||
autocfg::emit("tokio_no_const_mutex_new")
|
||||
}
|
||||
|
||||
if target_needs_atomic_u64_fallback {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_atomic_u64"
|
||||
autocfg::emit("tokio_no_atomic_u64")
|
||||
}
|
||||
|
||||
let target = ::std::env::var("TARGET").unwrap_or_default();
|
||||
|
||||
// We emit cfgs instead of using `target_family = "wasm"` that requires Rust 1.54.
|
||||
// Note that these cfgs are unavailable in `Cargo.toml`.
|
||||
if target.starts_with("wasm") {
|
||||
autocfg::emit("tokio_wasm");
|
||||
if target.contains("wasi") {
|
||||
autocfg::emit("tokio_wasi");
|
||||
} else {
|
||||
autocfg::emit("tokio_wasm_not_wasi");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -188,12 +188,12 @@ readiness, the driver's tick is packed into the atomic `usize`.
|
|||
The `ScheduledIo` readiness `AtomicUsize` is structured as:
|
||||
|
||||
```
|
||||
| reserved | generation | driver tick | readinesss |
|
||||
|----------+------------+--------------+------------|
|
||||
| 1 bit | 7 bits + 8 bits + 16 bits |
|
||||
| shutdown | generation | driver tick | readiness |
|
||||
|----------+------------+--------------+-----------|
|
||||
| 1 bit | 7 bits + 8 bits + 16 bits |
|
||||
```
|
||||
|
||||
The `reserved` and `generation` components exist today.
|
||||
The `shutdown` and `generation` components exist today.
|
||||
|
||||
The `readiness()` function returns a `ReadyEvent` value. This value includes the
|
||||
`tick` component read with the resource's readiness value. When
|
||||
|
|
11
zeroidc/vendor/tokio/external-types.toml
vendored
Normal file
11
zeroidc/vendor/tokio/external-types.toml
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# 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::*",
|
||||
]
|
||||
|
1
zeroidc/vendor/tokio/src/doc/mod.rs
vendored
1
zeroidc/vendor/tokio/src/doc/mod.rs
vendored
|
@ -21,4 +21,3 @@
|
|||
pub enum NotDefinedHere {}
|
||||
|
||||
pub mod os;
|
||||
pub mod winapi;
|
||||
|
|
66
zeroidc/vendor/tokio/src/doc/winapi.rs
vendored
66
zeroidc/vendor/tokio/src/doc/winapi.rs
vendored
|
@ -1,66 +0,0 @@
|
|||
//! See [winapi].
|
||||
//!
|
||||
//! [winapi]: https://docs.rs/winapi
|
||||
|
||||
/// See [winapi::shared](https://docs.rs/winapi/*/winapi/shared/index.html).
|
||||
pub mod shared {
|
||||
/// See [winapi::shared::winerror](https://docs.rs/winapi/*/winapi/shared/winerror/index.html).
|
||||
#[allow(non_camel_case_types)]
|
||||
pub mod winerror {
|
||||
/// See [winapi::shared::winerror::ERROR_ACCESS_DENIED][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/shared/winerror/constant.ERROR_ACCESS_DENIED.html
|
||||
pub type ERROR_ACCESS_DENIED = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [winapi::shared::winerror::ERROR_PIPE_BUSY][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/shared/winerror/constant.ERROR_PIPE_BUSY.html
|
||||
pub type ERROR_PIPE_BUSY = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [winapi::shared::winerror::ERROR_MORE_DATA][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/shared/winerror/constant.ERROR_MORE_DATA.html
|
||||
pub type ERROR_MORE_DATA = crate::doc::NotDefinedHere;
|
||||
}
|
||||
}
|
||||
|
||||
/// See [winapi::um](https://docs.rs/winapi/*/winapi/um/index.html).
|
||||
pub mod um {
|
||||
/// See [winapi::um::winbase](https://docs.rs/winapi/*/winapi/um/winbase/index.html).
|
||||
#[allow(non_camel_case_types)]
|
||||
pub mod winbase {
|
||||
/// See [winapi::um::winbase::PIPE_TYPE_MESSAGE][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_TYPE_MESSAGE.html
|
||||
pub type PIPE_TYPE_MESSAGE = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [winapi::um::winbase::PIPE_TYPE_BYTE][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_TYPE_BYTE.html
|
||||
pub type PIPE_TYPE_BYTE = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [winapi::um::winbase::PIPE_CLIENT_END][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_CLIENT_END.html
|
||||
pub type PIPE_CLIENT_END = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [winapi::um::winbase::PIPE_SERVER_END][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_SERVER_END.html
|
||||
pub type PIPE_SERVER_END = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [winapi::um::winbase::SECURITY_IDENTIFICATION][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.SECURITY_IDENTIFICATION.html
|
||||
pub type SECURITY_IDENTIFICATION = crate::doc::NotDefinedHere;
|
||||
}
|
||||
|
||||
/// See [winapi::um::minwinbase](https://docs.rs/winapi/*/winapi/um/minwinbase/index.html).
|
||||
#[allow(non_camel_case_types)]
|
||||
pub mod minwinbase {
|
||||
/// See [winapi::um::minwinbase::SECURITY_ATTRIBUTES][winapi]
|
||||
///
|
||||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/minwinbase/constant.SECURITY_ATTRIBUTES.html
|
||||
pub type SECURITY_ATTRIBUTES = crate::doc::NotDefinedHere;
|
||||
}
|
||||
}
|
39
zeroidc/vendor/tokio/src/fs/file.rs
vendored
39
zeroidc/vendor/tokio/src/fs/file.rs
vendored
|
@ -565,29 +565,30 @@ impl AsyncSeek for File {
|
|||
let me = self.get_mut();
|
||||
let inner = me.inner.get_mut();
|
||||
|
||||
loop {
|
||||
match inner.state {
|
||||
Busy(_) => panic!("must wait for poll_complete before calling start_seek"),
|
||||
Idle(ref mut buf_cell) => {
|
||||
let mut buf = buf_cell.take().unwrap();
|
||||
match inner.state {
|
||||
Busy(_) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"other file operation is pending, call poll_complete before start_seek",
|
||||
)),
|
||||
Idle(ref mut buf_cell) => {
|
||||
let mut buf = buf_cell.take().unwrap();
|
||||
|
||||
// Factor in any unread data from the buf
|
||||
if !buf.is_empty() {
|
||||
let n = buf.discard_read();
|
||||
// Factor in any unread data from the buf
|
||||
if !buf.is_empty() {
|
||||
let n = buf.discard_read();
|
||||
|
||||
if let SeekFrom::Current(ref mut offset) = pos {
|
||||
*offset += n;
|
||||
}
|
||||
if let SeekFrom::Current(ref mut offset) = pos {
|
||||
*offset += n;
|
||||
}
|
||||
|
||||
let std = me.std.clone();
|
||||
|
||||
inner.state = Busy(spawn_blocking(move || {
|
||||
let res = (&*std).seek(pos);
|
||||
(Operation::Seek(res), buf)
|
||||
}));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let std = me.std.clone();
|
||||
|
||||
inner.state = Busy(spawn_blocking(move || {
|
||||
let res = (&*std).seek(pos);
|
||||
(Operation::Seek(res), buf)
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
21
zeroidc/vendor/tokio/src/fs/file/tests.rs
vendored
21
zeroidc/vendor/tokio/src/fs/file/tests.rs
vendored
|
@ -955,3 +955,24 @@ fn partial_read_set_len_ok() {
|
|||
assert_eq!(n, FOO.len());
|
||||
assert_eq!(&buf[..n], FOO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn busy_file_seek_error() {
|
||||
let mut file = MockFile::default();
|
||||
let mut seq = Sequence::new();
|
||||
file.expect_inner_write()
|
||||
.once()
|
||||
.in_sequence(&mut seq)
|
||||
.returning(|_| Err(io::ErrorKind::Other.into()));
|
||||
|
||||
let mut file = crate::io::BufReader::new(File::from_std(file));
|
||||
{
|
||||
let mut t = task::spawn(file.write(HELLO));
|
||||
assert_ready_ok!(t.poll());
|
||||
}
|
||||
|
||||
pool::run_one();
|
||||
|
||||
let mut t = task::spawn(file.seek(SeekFrom::Start(0)));
|
||||
assert_ready_err!(t.poll());
|
||||
}
|
||||
|
|
2
zeroidc/vendor/tokio/src/fs/mocks.rs
vendored
2
zeroidc/vendor/tokio/src/fs/mocks.rs
vendored
|
@ -81,7 +81,7 @@ impl Write for &'_ MockFile {
|
|||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
tokio_thread_local! {
|
||||
static QUEUE: RefCell<VecDeque<Box<dyn FnOnce() + Send>>> = RefCell::new(VecDeque::new())
|
||||
}
|
||||
|
||||
|
|
18
zeroidc/vendor/tokio/src/fs/mod.rs
vendored
18
zeroidc/vendor/tokio/src/fs/mod.rs
vendored
|
@ -22,6 +22,24 @@
|
|||
//! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted
|
||||
//! to a *backup* thread immediately.
|
||||
//!
|
||||
//! **Warning**: These adapters may create a large number of temporary tasks,
|
||||
//! especially when reading large files. When performing a lot of operations
|
||||
//! in one batch, it may be significantly faster to use [`spawn_blocking`]
|
||||
//! directly:
|
||||
//!
|
||||
//! ```
|
||||
//! use tokio::fs::File;
|
||||
//! use std::io::{BufReader, BufRead};
|
||||
//! async fn count_lines(file: File) -> Result<usize, std::io::Error> {
|
||||
//! let file = file.into_std().await;
|
||||
//! tokio::task::spawn_blocking(move || {
|
||||
//! let line_count = BufReader::new(file).lines().count();
|
||||
//! Ok(line_count)
|
||||
//! }).await?
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! [`spawn_blocking`]: fn@crate::task::spawn_blocking
|
||||
//! [`AsyncRead`]: trait@crate::io::AsyncRead
|
||||
|
||||
mod canonicalize;
|
||||
|
|
6
zeroidc/vendor/tokio/src/fs/open_options.rs
vendored
6
zeroidc/vendor/tokio/src/fs/open_options.rs
vendored
|
@ -542,7 +542,7 @@ feature! {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use winapi::um::winbase::FILE_FLAG_DELETE_ON_CLOSE;
|
||||
/// use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_DELETE_ON_CLOSE;
|
||||
/// use tokio::fs::OpenOptions;
|
||||
///
|
||||
/// # #[tokio::main]
|
||||
|
@ -581,7 +581,7 @@ feature! {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use winapi::um::winnt::FILE_ATTRIBUTE_HIDDEN;
|
||||
/// use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_HIDDEN;
|
||||
/// use tokio::fs::OpenOptions;
|
||||
///
|
||||
/// # #[tokio::main]
|
||||
|
@ -624,7 +624,7 @@ feature! {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use winapi::um::winbase::SECURITY_IDENTIFICATION;
|
||||
/// use windows_sys::Win32::Storage::FileSystem::SECURITY_IDENTIFICATION;
|
||||
/// use tokio::fs::OpenOptions;
|
||||
///
|
||||
/// # #[tokio::main]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![allow(unreachable_pub)]
|
||||
//! Mock version of std::fs::OpenOptions;
|
||||
use mockall::mock;
|
||||
|
||||
|
|
93
zeroidc/vendor/tokio/src/fs/read_dir.rs
vendored
93
zeroidc/vendor/tokio/src/fs/read_dir.rs
vendored
|
@ -1,5 +1,6 @@
|
|||
use crate::fs::asyncify;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{FileType, Metadata};
|
||||
use std::future::Future;
|
||||
|
@ -19,6 +20,8 @@ use crate::blocking::spawn_blocking;
|
|||
#[cfg(not(test))]
|
||||
use crate::blocking::JoinHandle;
|
||||
|
||||
const CHUNK_SIZE: usize = 32;
|
||||
|
||||
/// Returns a stream over the entries within a directory.
|
||||
///
|
||||
/// This is an async version of [`std::fs::read_dir`](std::fs::read_dir)
|
||||
|
@ -29,12 +32,17 @@ use crate::blocking::JoinHandle;
|
|||
/// [`spawn_blocking`]: crate::task::spawn_blocking
|
||||
pub async fn read_dir(path: impl AsRef<Path>) -> io::Result<ReadDir> {
|
||||
let path = path.as_ref().to_owned();
|
||||
let std = asyncify(|| std::fs::read_dir(path)).await?;
|
||||
asyncify(|| -> io::Result<ReadDir> {
|
||||
let mut std = std::fs::read_dir(path)?;
|
||||
let mut buf = VecDeque::with_capacity(CHUNK_SIZE);
|
||||
ReadDir::next_chunk(&mut buf, &mut std);
|
||||
|
||||
Ok(ReadDir(State::Idle(Some(std))))
|
||||
Ok(ReadDir(State::Idle(Some((buf, std)))))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Reads the the entries in a directory.
|
||||
/// Reads the entries in a directory.
|
||||
///
|
||||
/// This struct is returned from the [`read_dir`] function of this module and
|
||||
/// will yield instances of [`DirEntry`]. Through a [`DirEntry`] information
|
||||
|
@ -58,8 +66,8 @@ pub struct ReadDir(State);
|
|||
|
||||
#[derive(Debug)]
|
||||
enum State {
|
||||
Idle(Option<std::fs::ReadDir>),
|
||||
Pending(JoinHandle<(Option<io::Result<std::fs::DirEntry>>, std::fs::ReadDir)>),
|
||||
Idle(Option<(VecDeque<io::Result<DirEntry>>, std::fs::ReadDir)>),
|
||||
Pending(JoinHandle<(VecDeque<io::Result<DirEntry>>, std::fs::ReadDir)>),
|
||||
}
|
||||
|
||||
impl ReadDir {
|
||||
|
@ -94,29 +102,57 @@ impl ReadDir {
|
|||
pub fn poll_next_entry(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>> {
|
||||
loop {
|
||||
match self.0 {
|
||||
State::Idle(ref mut std) => {
|
||||
let mut std = std.take().unwrap();
|
||||
State::Idle(ref mut data) => {
|
||||
let (buf, _) = data.as_mut().unwrap();
|
||||
|
||||
if let Some(ent) = buf.pop_front() {
|
||||
return Poll::Ready(ent.map(Some));
|
||||
};
|
||||
|
||||
let (mut buf, mut std) = data.take().unwrap();
|
||||
|
||||
self.0 = State::Pending(spawn_blocking(move || {
|
||||
let ret = std.next();
|
||||
(ret, std)
|
||||
ReadDir::next_chunk(&mut buf, &mut std);
|
||||
(buf, std)
|
||||
}));
|
||||
}
|
||||
State::Pending(ref mut rx) => {
|
||||
let (ret, std) = ready!(Pin::new(rx).poll(cx))?;
|
||||
self.0 = State::Idle(Some(std));
|
||||
let (mut buf, std) = ready!(Pin::new(rx).poll(cx))?;
|
||||
|
||||
let ret = match ret {
|
||||
Some(Ok(std)) => Ok(Some(DirEntry(Arc::new(std)))),
|
||||
let ret = match buf.pop_front() {
|
||||
Some(Ok(x)) => Ok(Some(x)),
|
||||
Some(Err(e)) => Err(e),
|
||||
None => Ok(None),
|
||||
};
|
||||
|
||||
self.0 = State::Idle(Some((buf, std)));
|
||||
|
||||
return Poll::Ready(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn next_chunk(buf: &mut VecDeque<io::Result<DirEntry>>, std: &mut std::fs::ReadDir) {
|
||||
for ret in std.by_ref().take(CHUNK_SIZE) {
|
||||
let success = ret.is_ok();
|
||||
|
||||
buf.push_back(ret.map(|std| DirEntry {
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks"
|
||||
)))]
|
||||
file_type: std.file_type().ok(),
|
||||
std: Arc::new(std),
|
||||
}));
|
||||
|
||||
if !success {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
feature! {
|
||||
|
@ -160,7 +196,16 @@ feature! {
|
|||
/// filesystem. Each entry can be inspected via methods to learn about the full
|
||||
/// path or possibly other metadata through per-platform extension traits.
|
||||
#[derive(Debug)]
|
||||
pub struct DirEntry(Arc<std::fs::DirEntry>);
|
||||
pub struct DirEntry {
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks"
|
||||
)))]
|
||||
file_type: Option<FileType>,
|
||||
std: Arc<std::fs::DirEntry>,
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
/// Returns the full path to the file that this entry represents.
|
||||
|
@ -193,7 +238,7 @@ impl DirEntry {
|
|||
///
|
||||
/// The exact text, of course, depends on what files you have in `.`.
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.0.path()
|
||||
self.std.path()
|
||||
}
|
||||
|
||||
/// Returns the bare file name of this directory entry without any other
|
||||
|
@ -214,7 +259,7 @@ impl DirEntry {
|
|||
/// # }
|
||||
/// ```
|
||||
pub fn file_name(&self) -> OsString {
|
||||
self.0.file_name()
|
||||
self.std.file_name()
|
||||
}
|
||||
|
||||
/// Returns the metadata for the file that this entry points at.
|
||||
|
@ -248,7 +293,7 @@ impl DirEntry {
|
|||
/// # }
|
||||
/// ```
|
||||
pub async fn metadata(&self) -> io::Result<Metadata> {
|
||||
let std = self.0.clone();
|
||||
let std = self.std.clone();
|
||||
asyncify(move || std.metadata()).await
|
||||
}
|
||||
|
||||
|
@ -283,13 +328,23 @@ impl DirEntry {
|
|||
/// # }
|
||||
/// ```
|
||||
pub async fn file_type(&self) -> io::Result<FileType> {
|
||||
let std = self.0.clone();
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks"
|
||||
)))]
|
||||
if let Some(file_type) = self.file_type {
|
||||
return Ok(file_type);
|
||||
}
|
||||
|
||||
let std = self.std.clone();
|
||||
asyncify(move || std.file_type()).await
|
||||
}
|
||||
|
||||
/// Returns a reference to the underlying `std::fs::DirEntry`.
|
||||
#[cfg(unix)]
|
||||
pub(super) fn as_inner(&self) -> &std::fs::DirEntry {
|
||||
&self.0
|
||||
&self.std
|
||||
}
|
||||
}
|
||||
|
|
11
zeroidc/vendor/tokio/src/future/block_on.rs
vendored
11
zeroidc/vendor/tokio/src/future/block_on.rs
vendored
|
@ -1,15 +1,22 @@
|
|||
use std::future::Future;
|
||||
|
||||
cfg_rt! {
|
||||
#[track_caller]
|
||||
pub(crate) fn block_on<F: Future>(f: F) -> F::Output {
|
||||
let mut e = crate::runtime::enter::enter(false);
|
||||
let mut e = crate::runtime::context::try_enter_blocking_region().expect(
|
||||
"Cannot block the current thread from within a runtime. This \
|
||||
happens because a function attempted to block the current \
|
||||
thread while the thread is being used to drive asynchronous \
|
||||
tasks."
|
||||
);
|
||||
e.block_on(f).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_not_rt! {
|
||||
#[track_caller]
|
||||
pub(crate) fn block_on<F: Future>(f: F) -> F::Output {
|
||||
let mut park = crate::park::thread::CachedParkThread::new();
|
||||
let mut park = crate::runtime::park::CachedParkThread::new();
|
||||
park.block_on(f).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
28
zeroidc/vendor/tokio/src/future/poll_fn.rs
vendored
28
zeroidc/vendor/tokio/src/future/poll_fn.rs
vendored
|
@ -7,13 +7,23 @@ use std::future::Future;
|
|||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
// This struct is intentionally `!Unpin` when `F` is `!Unpin`. This is to
|
||||
// mitigate the issue where rust puts noalias on mutable references to the
|
||||
// `PollFn` type if it is `Unpin`. If the closure has ownership of a future,
|
||||
// then this "leaks" and the future is affected by noalias too, which we don't
|
||||
// want.
|
||||
//
|
||||
// See this thread for more information:
|
||||
// <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
|
||||
//
|
||||
// The fact that `PollFn` is not `Unpin` when it shouldn't be is tested in
|
||||
// `tests/async_send_sync.rs`.
|
||||
|
||||
/// Future for the [`poll_fn`] function.
|
||||
pub struct PollFn<F> {
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<F> Unpin for PollFn<F> {}
|
||||
|
||||
/// Creates a new future wrapping around a function returning [`Poll`].
|
||||
pub fn poll_fn<T, F>(f: F) -> PollFn<F>
|
||||
where
|
||||
|
@ -34,7 +44,17 @@ where
|
|||
{
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
|
||||
(self.f)(cx)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
25
zeroidc/vendor/tokio/src/io/async_fd.rs
vendored
25
zeroidc/vendor/tokio/src/io/async_fd.rs
vendored
|
@ -1,4 +1,6 @@
|
|||
use crate::io::driver::{Handle, Interest, ReadyEvent, Registration};
|
||||
use crate::io::Interest;
|
||||
use crate::runtime::io::{ReadyEvent, Registration};
|
||||
use crate::runtime::scheduler;
|
||||
|
||||
use mio::unix::SourceFd;
|
||||
use std::io;
|
||||
|
@ -167,12 +169,18 @@ pub struct AsyncFdReadyMutGuard<'a, T: AsRawFd> {
|
|||
const ALL_INTEREST: Interest = Interest::READABLE.add(Interest::WRITABLE);
|
||||
|
||||
impl<T: AsRawFd> AsyncFd<T> {
|
||||
#[inline]
|
||||
/// Creates an AsyncFd backed by (and taking ownership of) an object
|
||||
/// implementing [`AsRawFd`]. The backing file descriptor is cached at the
|
||||
/// time of creation.
|
||||
///
|
||||
/// This method must be called in the context of a tokio runtime.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is no current reactor set, or if the `rt`
|
||||
/// feature flag is not enabled.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn new(inner: T) -> io::Result<Self>
|
||||
where
|
||||
T: AsRawFd,
|
||||
|
@ -180,19 +188,26 @@ impl<T: AsRawFd> AsyncFd<T> {
|
|||
Self::with_interest(inner, ALL_INTEREST)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Creates new instance as `new` with additional ability to customize interest,
|
||||
/// allowing to specify whether file descriptor will be polled for read, write or both.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if there is no current reactor set, or if the `rt`
|
||||
/// feature flag is not enabled.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn with_interest(inner: T, interest: Interest) -> io::Result<Self>
|
||||
where
|
||||
T: AsRawFd,
|
||||
{
|
||||
Self::new_with_handle_and_interest(inner, Handle::current(), interest)
|
||||
Self::new_with_handle_and_interest(inner, scheduler::Handle::current(), interest)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn new_with_handle_and_interest(
|
||||
inner: T,
|
||||
handle: Handle,
|
||||
handle: scheduler::Handle,
|
||||
interest: Interest,
|
||||
) -> io::Result<Self> {
|
||||
let fd = inner.as_raw_fd();
|
||||
|
|
3
zeroidc/vendor/tokio/src/io/blocking.rs
vendored
3
zeroidc/vendor/tokio/src/io/blocking.rs
vendored
|
@ -34,8 +34,9 @@ enum State<T> {
|
|||
Busy(sys::Blocking<(io::Result<usize>, Buf, T)>),
|
||||
}
|
||||
|
||||
cfg_io_std! {
|
||||
cfg_io_blocking! {
|
||||
impl<T> Blocking<T> {
|
||||
#[cfg_attr(feature = "fs", allow(dead_code))]
|
||||
pub(crate) fn new(inner: T) -> Blocking<T> {
|
||||
Blocking {
|
||||
inner: Some(inner),
|
||||
|
|
6
zeroidc/vendor/tokio/src/io/bsd/poll_aio.rs
vendored
6
zeroidc/vendor/tokio/src/io/bsd/poll_aio.rs
vendored
|
@ -1,6 +1,8 @@
|
|||
//! Use POSIX AIO futures with Tokio.
|
||||
|
||||
use crate::io::driver::{Handle, Interest, ReadyEvent, Registration};
|
||||
use crate::io::interest::Interest;
|
||||
use crate::runtime::io::{ReadyEvent, Registration};
|
||||
use crate::runtime::scheduler;
|
||||
use mio::event::Source;
|
||||
use mio::Registry;
|
||||
use mio::Token;
|
||||
|
@ -117,7 +119,7 @@ impl<E: AioSource> Aio<E> {
|
|||
|
||||
fn new_with_interest(io: E, interest: Interest) -> io::Result<Self> {
|
||||
let mut io = MioSource(io);
|
||||
let handle = Handle::current();
|
||||
let handle = scheduler::Handle::current();
|
||||
let registration = Registration::new_with_interest_and_handle(&mut io, interest, handle)?;
|
||||
Ok(Self { io, registration })
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![cfg_attr(not(feature = "net"), allow(dead_code, unreachable_pub))]
|
||||
|
||||
use crate::io::driver::Ready;
|
||||
use crate::io::ready::Ready;
|
||||
|
||||
use std::fmt;
|
||||
use std::ops;
|
||||
|
@ -100,7 +100,7 @@ impl Interest {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub(super) fn mask(self) -> Ready {
|
||||
pub(crate) fn mask(self) -> Ready {
|
||||
match self {
|
||||
Interest::READABLE => Ready::READABLE | Ready::READ_CLOSED,
|
||||
Interest::WRITABLE => Ready::WRITABLE | Ready::WRITE_CLOSED,
|
16
zeroidc/vendor/tokio/src/io/mod.rs
vendored
16
zeroidc/vendor/tokio/src/io/mod.rs
vendored
|
@ -1,5 +1,3 @@
|
|||
#![cfg_attr(loom, allow(dead_code, unreachable_pub))]
|
||||
|
||||
//! Traits, helpers, and type definitions for asynchronous I/O functionality.
|
||||
//!
|
||||
//! This module is the asynchronous version of `std::io`. Primarily, it
|
||||
|
@ -180,6 +178,12 @@
|
|||
//! [`Sink`]: https://docs.rs/futures/0.3/futures/sink/trait.Sink.html
|
||||
//! [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html
|
||||
//! [`Write`]: std::io::Write
|
||||
|
||||
#![cfg_attr(
|
||||
not(all(feature = "rt", feature = "net")),
|
||||
allow(dead_code, unused_imports)
|
||||
)]
|
||||
|
||||
cfg_io_blocking! {
|
||||
pub(crate) mod blocking;
|
||||
}
|
||||
|
@ -205,15 +209,19 @@ pub use self::read_buf::ReadBuf;
|
|||
pub use std::io::{Error, ErrorKind, Result, SeekFrom};
|
||||
|
||||
cfg_io_driver_impl! {
|
||||
pub(crate) mod driver;
|
||||
pub(crate) mod interest;
|
||||
pub(crate) mod ready;
|
||||
|
||||
cfg_net! {
|
||||
pub use driver::{Interest, Ready};
|
||||
pub use interest::Interest;
|
||||
pub use ready::Ready;
|
||||
}
|
||||
|
||||
#[cfg_attr(tokio_wasi, allow(unused_imports))]
|
||||
mod poll_evented;
|
||||
|
||||
#[cfg(not(loom))]
|
||||
#[cfg_attr(tokio_wasi, allow(unused_imports))]
|
||||
pub(crate) use poll_evented::PollEvented;
|
||||
}
|
||||
|
||||
|
|
83
zeroidc/vendor/tokio/src/io/poll_evented.rs
vendored
83
zeroidc/vendor/tokio/src/io/poll_evented.rs
vendored
|
@ -1,4 +1,6 @@
|
|||
use crate::io::driver::{Handle, Interest, Registration};
|
||||
use crate::io::interest::Interest;
|
||||
use crate::runtime::io::Registration;
|
||||
use crate::runtime::scheduler;
|
||||
|
||||
use mio::event::Source;
|
||||
use std::fmt;
|
||||
|
@ -11,7 +13,7 @@ cfg_io_driver! {
|
|||
/// [`std::io::Write`] traits with the reactor that drives it.
|
||||
///
|
||||
/// `PollEvented` uses [`Registration`] internally to take a type that
|
||||
/// implements [`mio::event::Source`] as well as [`std::io::Read`] and or
|
||||
/// implements [`mio::event::Source`] as well as [`std::io::Read`] and/or
|
||||
/// [`std::io::Write`] and associate it with a reactor that will drive it.
|
||||
///
|
||||
/// Once the [`mio::event::Source`] type is wrapped by `PollEvented`, it can be
|
||||
|
@ -41,12 +43,12 @@ cfg_io_driver! {
|
|||
/// [`poll_read_ready`] again will also indicate read readiness.
|
||||
///
|
||||
/// When the operation is attempted and is unable to succeed due to the I/O
|
||||
/// resource not being ready, the caller must call `clear_readiness`.
|
||||
/// resource not being ready, the caller must call [`clear_readiness`].
|
||||
/// This clears the readiness state until a new readiness event is received.
|
||||
///
|
||||
/// This allows the caller to implement additional functions. For example,
|
||||
/// [`TcpListener`] implements poll_accept by using [`poll_read_ready`] and
|
||||
/// `clear_read_ready`.
|
||||
/// [`clear_readiness`].
|
||||
///
|
||||
/// ## Platform-specific events
|
||||
///
|
||||
|
@ -57,6 +59,7 @@ cfg_io_driver! {
|
|||
/// [`AsyncRead`]: crate::io::AsyncRead
|
||||
/// [`AsyncWrite`]: crate::io::AsyncWrite
|
||||
/// [`TcpListener`]: crate::net::TcpListener
|
||||
/// [`clear_readiness`]: Registration::clear_readiness
|
||||
/// [`poll_read_ready`]: Registration::poll_read_ready
|
||||
/// [`poll_write_ready`]: Registration::poll_write_ready
|
||||
pub(crate) struct PollEvented<E: Source> {
|
||||
|
@ -77,6 +80,7 @@ impl<E: Source> PollEvented<E> {
|
|||
/// The runtime is usually set implicitly when this function is called
|
||||
/// from a future driven by a tokio runtime, otherwise runtime can be set
|
||||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
|
||||
#[track_caller]
|
||||
#[cfg_attr(feature = "signal", allow(unused))]
|
||||
pub(crate) fn new(io: E) -> io::Result<Self> {
|
||||
PollEvented::new_with_interest(io, Interest::READABLE | Interest::WRITABLE)
|
||||
|
@ -97,15 +101,17 @@ impl<E: Source> PollEvented<E> {
|
|||
/// a future driven by a tokio runtime, otherwise runtime can be set
|
||||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter)
|
||||
/// function.
|
||||
#[track_caller]
|
||||
#[cfg_attr(feature = "signal", allow(unused))]
|
||||
pub(crate) fn new_with_interest(io: E, interest: Interest) -> io::Result<Self> {
|
||||
Self::new_with_interest_and_handle(io, interest, Handle::current())
|
||||
Self::new_with_interest_and_handle(io, interest, scheduler::Handle::current())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn new_with_interest_and_handle(
|
||||
mut io: E,
|
||||
interest: Interest,
|
||||
handle: Handle,
|
||||
handle: scheduler::Handle,
|
||||
) -> io::Result<Self> {
|
||||
let registration = Registration::new_with_interest_and_handle(&mut io, interest, handle)?;
|
||||
Ok(Self {
|
||||
|
@ -115,11 +121,7 @@ impl<E: Source> PollEvented<E> {
|
|||
}
|
||||
|
||||
/// Returns a reference to the registration.
|
||||
#[cfg(any(
|
||||
feature = "net",
|
||||
all(unix, feature = "process"),
|
||||
all(unix, feature = "signal"),
|
||||
))]
|
||||
#[cfg(any(feature = "net"))]
|
||||
pub(crate) fn registration(&self) -> &Registration {
|
||||
&self.registration
|
||||
}
|
||||
|
@ -134,7 +136,7 @@ impl<E: Source> PollEvented<E> {
|
|||
}
|
||||
|
||||
feature! {
|
||||
#![any(feature = "net", feature = "process")]
|
||||
#![any(feature = "net", all(unix, feature = "process"))]
|
||||
|
||||
use crate::io::ReadBuf;
|
||||
use std::task::{Context, Poll};
|
||||
|
@ -151,16 +153,32 @@ feature! {
|
|||
{
|
||||
use std::io::Read;
|
||||
|
||||
let n = ready!(self.registration.poll_read_io(cx, || {
|
||||
let b = &mut *(buf.unfilled_mut() as *mut [std::mem::MaybeUninit<u8>] as *mut [u8]);
|
||||
self.io.as_ref().unwrap().read(b)
|
||||
}))?;
|
||||
loop {
|
||||
let evt = ready!(self.registration.poll_read_ready(cx))?;
|
||||
|
||||
// Safety: We trust `TcpStream::read` to have filled up `n` bytes in the
|
||||
// buffer.
|
||||
buf.assume_init(n);
|
||||
buf.advance(n);
|
||||
Poll::Ready(Ok(()))
|
||||
let b = &mut *(buf.unfilled_mut() as *mut [std::mem::MaybeUninit<u8>] as *mut [u8]);
|
||||
let len = b.len();
|
||||
|
||||
match self.io.as_ref().unwrap().read(b) {
|
||||
Ok(n) => {
|
||||
// if we read a partially full buffer, this is sufficient on unix to show
|
||||
// that the socket buffer has been drained
|
||||
if n > 0 && (!cfg!(windows) && n < len) {
|
||||
self.registration.clear_readiness(evt);
|
||||
}
|
||||
|
||||
// Safety: We trust `TcpStream::read` to have filled up `n` bytes in the
|
||||
// buffer.
|
||||
buf.assume_init(n);
|
||||
buf.advance(n);
|
||||
return Poll::Ready(Ok(()));
|
||||
},
|
||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
self.registration.clear_readiness(evt);
|
||||
}
|
||||
Err(e) => return Poll::Ready(Err(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn poll_write<'a>(&'a self, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>>
|
||||
|
@ -168,10 +186,29 @@ feature! {
|
|||
&'a E: io::Write + 'a,
|
||||
{
|
||||
use std::io::Write;
|
||||
self.registration.poll_write_io(cx, || self.io.as_ref().unwrap().write(buf))
|
||||
|
||||
loop {
|
||||
let evt = ready!(self.registration.poll_write_ready(cx))?;
|
||||
|
||||
match self.io.as_ref().unwrap().write(buf) {
|
||||
Ok(n) => {
|
||||
// if we write only part of our buffer, this is sufficient on unix to show
|
||||
// that the socket buffer is full
|
||||
if n > 0 && (!cfg!(windows) && n < buf.len()) {
|
||||
self.registration.clear_readiness(evt);
|
||||
}
|
||||
|
||||
return Poll::Ready(Ok(n));
|
||||
},
|
||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
self.registration.clear_readiness(evt);
|
||||
}
|
||||
Err(e) => return Poll::Ready(Err(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg(any(feature = "net", feature = "process"))]
|
||||
pub(crate) fn poll_write_vectored<'a>(
|
||||
&'a self,
|
||||
cx: &mut Context<'_>,
|
||||
|
|
4
zeroidc/vendor/tokio/src/io/read_buf.rs
vendored
4
zeroidc/vendor/tokio/src/io/read_buf.rs
vendored
|
@ -152,6 +152,7 @@ impl<'a> ReadBuf<'a> {
|
|||
///
|
||||
/// Panics if `self.remaining()` is less than `n`.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
|
||||
assert!(self.remaining() >= n, "n overflows remaining");
|
||||
|
||||
|
@ -195,6 +196,7 @@ impl<'a> ReadBuf<'a> {
|
|||
///
|
||||
/// Panics if the filled region of the buffer would become larger than the initialized region.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
let new = self.filled.checked_add(n).expect("filled overflow");
|
||||
self.set_filled(new);
|
||||
|
@ -211,6 +213,7 @@ impl<'a> ReadBuf<'a> {
|
|||
///
|
||||
/// Panics if the filled region of the buffer would become larger than the initialized region.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn set_filled(&mut self, n: usize) {
|
||||
assert!(
|
||||
n <= self.initialized,
|
||||
|
@ -241,6 +244,7 @@ impl<'a> ReadBuf<'a> {
|
|||
///
|
||||
/// Panics if `self.remaining()` is less than `buf.len()`.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn put_slice(&mut self, buf: &[u8]) {
|
||||
assert!(
|
||||
self.remaining() >= buf.len(),
|
||||
|
|
|
@ -12,7 +12,7 @@ const WRITE_CLOSED: usize = 0b0_1000;
|
|||
///
|
||||
/// `Ready` tracks which operation an I/O resource is ready to perform.
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Ready(usize);
|
||||
|
||||
impl Ready {
|
1
zeroidc/vendor/tokio/src/io/split.rs
vendored
1
zeroidc/vendor/tokio/src/io/split.rs
vendored
|
@ -74,6 +74,7 @@ impl<T> ReadHalf<T> {
|
|||
/// same `split` operation this method will panic.
|
||||
/// This can be checked ahead of time by comparing the stream ID
|
||||
/// of the two halves.
|
||||
#[track_caller]
|
||||
pub fn unsplit(self, wr: WriteHalf<T>) -> T {
|
||||
if self.is_pair_of(&wr) {
|
||||
drop(wr);
|
||||
|
|
|
@ -69,7 +69,7 @@ cfg_io_util! {
|
|||
|
||||
/// Creates a future which will rewind to the beginning of the stream.
|
||||
///
|
||||
/// This is convenience method, equivalent to to `self.seek(SeekFrom::Start(0))`.
|
||||
/// This is convenience method, equivalent to `self.seek(SeekFrom::Start(0))`.
|
||||
fn rewind(&mut self) -> Seek<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
|
|
|
@ -406,7 +406,7 @@ cfg_io_util! {
|
|||
/// ```
|
||||
fn write_u8(&mut self, n: u8) -> WriteU8;
|
||||
|
||||
/// Writes an unsigned 8-bit integer to the underlying writer.
|
||||
/// Writes a signed 8-bit integer to the underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
|
@ -425,7 +425,7 @@ cfg_io_util! {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write unsigned 8 bit integers to a `AsyncWrite`:
|
||||
/// Write signed 8 bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
|
@ -434,10 +434,10 @@ cfg_io_util! {
|
|||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_u8(2).await?;
|
||||
/// writer.write_u8(5).await?;
|
||||
/// writer.write_i8(-2).await?;
|
||||
/// writer.write_i8(126).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x02\x05");
|
||||
/// assert_eq!(writer, b"\xFE\x7E");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
|
|
62
zeroidc/vendor/tokio/src/io/util/copy.rs
vendored
62
zeroidc/vendor/tokio/src/io/util/copy.rs
vendored
|
@ -27,6 +27,51 @@ impl CopyBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
fn poll_fill_buf<R>(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
reader: Pin<&mut R>,
|
||||
) -> Poll<io::Result<()>>
|
||||
where
|
||||
R: AsyncRead + ?Sized,
|
||||
{
|
||||
let me = &mut *self;
|
||||
let mut buf = ReadBuf::new(&mut me.buf);
|
||||
buf.set_filled(me.cap);
|
||||
|
||||
let res = reader.poll_read(cx, &mut buf);
|
||||
if let Poll::Ready(Ok(_)) = res {
|
||||
let filled_len = buf.filled().len();
|
||||
me.read_done = me.cap == filled_len;
|
||||
me.cap = filled_len;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn poll_write_buf<R, W>(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
mut reader: Pin<&mut R>,
|
||||
mut writer: Pin<&mut W>,
|
||||
) -> Poll<io::Result<usize>>
|
||||
where
|
||||
R: AsyncRead + ?Sized,
|
||||
W: AsyncWrite + ?Sized,
|
||||
{
|
||||
let me = &mut *self;
|
||||
match writer.as_mut().poll_write(cx, &me.buf[me.pos..me.cap]) {
|
||||
Poll::Pending => {
|
||||
// Top up the buffer towards full if we can read a bit more
|
||||
// data - this should improve the chances of a large write
|
||||
if !me.read_done && me.cap < me.buf.len() {
|
||||
ready!(me.poll_fill_buf(cx, reader.as_mut()))?;
|
||||
}
|
||||
Poll::Pending
|
||||
}
|
||||
res => res,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn poll_copy<R, W>(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
|
@ -41,10 +86,10 @@ impl CopyBuffer {
|
|||
// If our buffer is empty, then we need to read some data to
|
||||
// continue.
|
||||
if self.pos == self.cap && !self.read_done {
|
||||
let me = &mut *self;
|
||||
let mut buf = ReadBuf::new(&mut me.buf);
|
||||
self.pos = 0;
|
||||
self.cap = 0;
|
||||
|
||||
match reader.as_mut().poll_read(cx, &mut buf) {
|
||||
match self.poll_fill_buf(cx, reader.as_mut()) {
|
||||
Poll::Ready(Ok(_)) => (),
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
|
||||
Poll::Pending => {
|
||||
|
@ -58,20 +103,11 @@ impl CopyBuffer {
|
|||
return Poll::Pending;
|
||||
}
|
||||
}
|
||||
|
||||
let n = buf.filled().len();
|
||||
if n == 0 {
|
||||
self.read_done = true;
|
||||
} else {
|
||||
self.pos = 0;
|
||||
self.cap = n;
|
||||
}
|
||||
}
|
||||
|
||||
// If our buffer has some data, let's write it out!
|
||||
while self.pos < self.cap {
|
||||
let me = &mut *self;
|
||||
let i = ready!(writer.as_mut().poll_write(cx, &me.buf[me.pos..me.cap]))?;
|
||||
let i = ready!(self.poll_write_buf(cx, reader.as_mut(), writer.as_mut()))?;
|
||||
if i == 0 {
|
||||
return Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::WriteZero,
|
||||
|
|
2
zeroidc/vendor/tokio/src/io/util/empty.rs
vendored
2
zeroidc/vendor/tokio/src/io/util/empty.rs
vendored
|
@ -77,7 +77,7 @@ impl fmt::Debug for Empty {
|
|||
|
||||
cfg_coop! {
|
||||
fn poll_proceed_and_make_progress(cx: &mut Context<'_>) -> Poll<()> {
|
||||
let coop = ready!(crate::coop::poll_proceed(cx));
|
||||
let coop = ready!(crate::runtime::coop::poll_proceed(cx));
|
||||
coop.made_progress();
|
||||
Poll::Ready(())
|
||||
}
|
||||
|
|
4
zeroidc/vendor/tokio/src/io/util/mem.rs
vendored
4
zeroidc/vendor/tokio/src/io/util/mem.rs
vendored
|
@ -233,7 +233,7 @@ impl AsyncRead for Pipe {
|
|||
cx: &mut task::Context<'_>,
|
||||
buf: &mut ReadBuf<'_>,
|
||||
) -> Poll<std::io::Result<()>> {
|
||||
let coop = ready!(crate::coop::poll_proceed(cx));
|
||||
let coop = ready!(crate::runtime::coop::poll_proceed(cx));
|
||||
|
||||
let ret = self.poll_read_internal(cx, buf);
|
||||
if ret.is_ready() {
|
||||
|
@ -261,7 +261,7 @@ impl AsyncWrite for Pipe {
|
|||
cx: &mut task::Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<std::io::Result<usize>> {
|
||||
let coop = ready!(crate::coop::poll_proceed(cx));
|
||||
let coop = ready!(crate::runtime::coop::poll_proceed(cx));
|
||||
|
||||
let ret = self.poll_write_internal(cx, buf);
|
||||
if ret.is_ready() {
|
||||
|
|
2
zeroidc/vendor/tokio/src/io/util/read.rs
vendored
2
zeroidc/vendor/tokio/src/io/util/read.rs
vendored
|
@ -48,7 +48,7 @@ where
|
|||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<usize>> {
|
||||
let me = self.project();
|
||||
let mut buf = ReadBuf::new(*me.buf);
|
||||
let mut buf = ReadBuf::new(me.buf);
|
||||
ready!(Pin::new(me.reader).poll_read(cx, &mut buf))?;
|
||||
Poll::Ready(Ok(buf.filled().len()))
|
||||
}
|
||||
|
|
131
zeroidc/vendor/tokio/src/lib.rs
vendored
131
zeroidc/vendor/tokio/src/lib.rs
vendored
|
@ -1,7 +1,9 @@
|
|||
#![allow(
|
||||
clippy::cognitive_complexity,
|
||||
clippy::large_enum_variant,
|
||||
clippy::needless_doctest_main
|
||||
clippy::module_inception,
|
||||
clippy::needless_doctest_main,
|
||||
clippy::declare_interior_mutable_const
|
||||
)]
|
||||
#![warn(
|
||||
missing_debug_implementations,
|
||||
|
@ -16,6 +18,7 @@
|
|||
))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(docsrs, allow(unused_attributes))]
|
||||
#![cfg_attr(loom, allow(dead_code, unreachable_pub))]
|
||||
|
||||
//! A runtime for writing reliable network applications without compromising speed.
|
||||
//!
|
||||
|
@ -152,7 +155,7 @@
|
|||
//! provide the functionality you need.
|
||||
//!
|
||||
//! Using the runtime requires the "rt" or "rt-multi-thread" feature flags, to
|
||||
//! enable the basic [single-threaded scheduler][rt] and the [thread-pool
|
||||
//! enable the current-thread [single-threaded scheduler][rt] and the [multi-thread
|
||||
//! scheduler][rt-multi-thread], respectively. See the [`runtime` module
|
||||
//! documentation][rt-features] for details. In addition, the "macros" feature
|
||||
//! flag enables the `#[tokio::main]` and `#[tokio::test]` attributes.
|
||||
|
@ -171,12 +174,15 @@
|
|||
//! swapping the currently running task on each thread. However, this kind of
|
||||
//! swapping can only happen at `.await` points, so code that spends a long time
|
||||
//! without reaching an `.await` will prevent other tasks from running. To
|
||||
//! combat this, Tokio provides two kinds of threads: Core threads and blocking
|
||||
//! threads. The core threads are where all asynchronous code runs, and Tokio
|
||||
//! will by default spawn one for each CPU core. The blocking threads are
|
||||
//! spawned on demand, can be used to run blocking code that would otherwise
|
||||
//! block other tasks from running and are kept alive when not used for a certain
|
||||
//! amount of time which can be configured with [`thread_keep_alive`].
|
||||
//! combat this, Tokio provides two kinds of threads: Core threads and blocking threads.
|
||||
//!
|
||||
//! The core threads are where all asynchronous code runs, and Tokio will by default
|
||||
//! spawn one for each CPU core. You can use the environment variable `TOKIO_WORKER_THREADS`
|
||||
//! to override the default value.
|
||||
//!
|
||||
//! The blocking threads are spawned on demand, can be used to run blocking code
|
||||
//! that would otherwise block other tasks from running and are kept alive when
|
||||
//! not used for a certain amount of time which can be configured with [`thread_keep_alive`].
|
||||
//! Since it is not possible for Tokio to swap out blocking tasks, like it
|
||||
//! can do with asynchronous code, the upper limit on the number of blocking
|
||||
//! threads is very large. These limits can be configured on the [`Builder`].
|
||||
|
@ -309,7 +315,7 @@
|
|||
//! need.
|
||||
//!
|
||||
//! - `full`: Enables all features listed below except `test-util` and `tracing`.
|
||||
//! - `rt`: Enables `tokio::spawn`, the basic (current thread) scheduler,
|
||||
//! - `rt`: Enables `tokio::spawn`, the current-thread scheduler,
|
||||
//! and non-scheduler utilities.
|
||||
//! - `rt-multi-thread`: Enables the heavier, multi-threaded, work-stealing scheduler.
|
||||
//! - `io-util`: Enables the IO based `Ext` traits.
|
||||
|
@ -325,20 +331,15 @@
|
|||
//! - `signal`: Enables all `tokio::signal` types.
|
||||
//! - `fs`: Enables `tokio::fs` types.
|
||||
//! - `test-util`: Enables testing based infrastructure for the Tokio runtime.
|
||||
//! - `parking_lot`: As a potential optimization, use the _parking_lot_ crate's
|
||||
//! synchronization primitives internally. Also, this
|
||||
//! dependency is necessary to construct some of our primitives
|
||||
//! in a const context. MSRV may increase according to the
|
||||
//! _parking_lot_ release in use.
|
||||
//!
|
||||
//! _Note: `AsyncRead` and `AsyncWrite` traits do not require any features and are
|
||||
//! always available._
|
||||
//!
|
||||
//! ### Internal features
|
||||
//!
|
||||
//! These features do not expose any new API, but influence internal
|
||||
//! implementation aspects of Tokio, and can pull in additional
|
||||
//! dependencies.
|
||||
//!
|
||||
//! - `parking_lot`: As a potential optimization, use the _parking_lot_ crate's
|
||||
//! synchronization primitives internally. MSRV may increase according to the
|
||||
//! _parking_lot_ release in use.
|
||||
//!
|
||||
//! ### Unstable features
|
||||
//!
|
||||
//! Some feature flags are only available when specifying the `tokio_unstable` flag:
|
||||
|
@ -347,9 +348,12 @@
|
|||
//!
|
||||
//! Likewise, some parts of the API are only available with the same flag:
|
||||
//!
|
||||
//! - [`task::JoinSet`]
|
||||
//! - [`task::Builder`]
|
||||
//!
|
||||
//! - Some methods on [`task::JoinSet`]
|
||||
//! - [`runtime::RuntimeMetrics`]
|
||||
//! - [`runtime::Builder::unhandled_panic`]
|
||||
//! - [`task::Id`]
|
||||
//!
|
||||
//! This flag enables **unstable** features. The public API of these features
|
||||
//! may break in 1.x releases. To enable these features, the `--cfg
|
||||
//! tokio_unstable` argument must be passed to `rustc` when compiling. This
|
||||
|
@ -379,6 +383,39 @@
|
|||
//!
|
||||
//! [unstable features]: https://internals.rust-lang.org/t/feature-request-unstable-opt-in-non-transitive-crate-features/16193#why-not-a-crate-feature-2
|
||||
//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
|
||||
//!
|
||||
//! ## WASM support
|
||||
//!
|
||||
//! Tokio has some limited support for the WASM platform. Without the
|
||||
//! `tokio_unstable` flag, the following features are supported:
|
||||
//!
|
||||
//! * `sync`
|
||||
//! * `macros`
|
||||
//! * `io-util`
|
||||
//! * `rt`
|
||||
//! * `time`
|
||||
//!
|
||||
//! Enabling any other feature (including `full`) will cause a compilation
|
||||
//! failure.
|
||||
//!
|
||||
//! The `time` module will only work on WASM platforms that have support for
|
||||
//! timers (e.g. wasm32-wasi). The timing functions will panic if used on a WASM
|
||||
//! platform that does not support timers.
|
||||
//!
|
||||
//! Note also that if the runtime becomes indefinitely idle, it will panic
|
||||
//! immediately instead of blocking forever. On platforms that don't support
|
||||
//! time, this means that the runtime can never be idle in any way.
|
||||
//!
|
||||
//! ### Unstable WASM support
|
||||
//!
|
||||
//! Tokio also has unstable support for some additional WASM features. This
|
||||
//! requires the use of the `tokio_unstable` flag.
|
||||
//!
|
||||
//! Using this flag enables the use of `tokio::net` on the wasm32-wasi target.
|
||||
//! However, not all methods are available on the networking types as WASI
|
||||
//! currently does not support the creation of new sockets from within WASM.
|
||||
//! Because of this, sockets must currently be created via the `FromRawFd`
|
||||
//! trait.
|
||||
|
||||
// Test that pointer width is compatible. This asserts that e.g. usize is at
|
||||
// least 32 bits, which a lot of components in Tokio currently assumes.
|
||||
|
@ -393,6 +430,37 @@ compile_error! {
|
|||
"Tokio requires the platform pointer width to be 32, 64, or 128 bits"
|
||||
}
|
||||
|
||||
// Ensure that our build script has correctly set cfg flags for wasm.
|
||||
//
|
||||
// Each condition is written all(a, not(b)). This should be read as
|
||||
// "if a, then we must also have b".
|
||||
#[cfg(any(
|
||||
all(target_arch = "wasm32", not(tokio_wasm)),
|
||||
all(target_arch = "wasm64", not(tokio_wasm)),
|
||||
all(target_family = "wasm", not(tokio_wasm)),
|
||||
all(target_os = "wasi", not(tokio_wasm)),
|
||||
all(target_os = "wasi", not(tokio_wasi)),
|
||||
all(target_os = "wasi", tokio_wasm_not_wasi),
|
||||
all(tokio_wasm, not(any(target_arch = "wasm32", target_arch = "wasm64"))),
|
||||
all(tokio_wasm_not_wasi, not(tokio_wasm)),
|
||||
all(tokio_wasi, not(tokio_wasm))
|
||||
))]
|
||||
compile_error!("Tokio's build script has incorrectly detected wasm.");
|
||||
|
||||
#[cfg(all(
|
||||
not(tokio_unstable),
|
||||
tokio_wasm,
|
||||
any(
|
||||
feature = "fs",
|
||||
feature = "io-std",
|
||||
feature = "net",
|
||||
feature = "process",
|
||||
feature = "rt-multi-thread",
|
||||
feature = "signal"
|
||||
)
|
||||
))]
|
||||
compile_error!("Only features sync,macros,io-util,rt,time are supported on wasm.");
|
||||
|
||||
// Includes re-exports used by macros.
|
||||
//
|
||||
// This module is not intended to be part of the public API. In general, any
|
||||
|
@ -411,20 +479,25 @@ pub mod io;
|
|||
pub mod net;
|
||||
|
||||
mod loom;
|
||||
mod park;
|
||||
|
||||
cfg_process! {
|
||||
pub mod process;
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "net", feature = "fs", feature = "io-std"))]
|
||||
#[cfg(any(
|
||||
feature = "fs",
|
||||
feature = "io-std",
|
||||
feature = "net",
|
||||
all(windows, feature = "process"),
|
||||
))]
|
||||
mod blocking;
|
||||
|
||||
cfg_rt! {
|
||||
pub mod runtime;
|
||||
}
|
||||
|
||||
pub(crate) mod coop;
|
||||
cfg_not_rt! {
|
||||
pub(crate) mod runtime;
|
||||
}
|
||||
|
||||
cfg_signal! {
|
||||
pub mod signal;
|
||||
|
@ -508,14 +581,6 @@ pub(crate) use self::doc::os;
|
|||
#[allow(unused)]
|
||||
pub(crate) use std::os;
|
||||
|
||||
#[cfg(docsrs)]
|
||||
#[allow(unused)]
|
||||
pub(crate) use self::doc::winapi;
|
||||
|
||||
#[cfg(all(not(docsrs), windows, feature = "net"))]
|
||||
#[allow(unused)]
|
||||
pub(crate) use winapi;
|
||||
|
||||
cfg_macros! {
|
||||
/// Implementation detail of the `select!` macro. This macro is **not**
|
||||
/// intended to be used as part of the public API and is permitted to
|
||||
|
|
12
zeroidc/vendor/tokio/src/loom/mocked.rs
vendored
12
zeroidc/vendor/tokio/src/loom/mocked.rs
vendored
|
@ -25,6 +25,13 @@ pub(crate) mod sync {
|
|||
}
|
||||
}
|
||||
pub(crate) use loom::sync::*;
|
||||
|
||||
pub(crate) mod atomic {
|
||||
pub(crate) use loom::sync::atomic::*;
|
||||
|
||||
// TODO: implement a loom version
|
||||
pub(crate) type StaticAtomicU64 = std::sync::atomic::AtomicU64;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod rand {
|
||||
|
@ -38,3 +45,8 @@ pub(crate) mod sys {
|
|||
2
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod thread {
|
||||
pub use loom::lazy_static::AccessError;
|
||||
pub use loom::thread::*;
|
||||
}
|
||||
|
|
34
zeroidc/vendor/tokio/src/loom/std/atomic_ptr.rs
vendored
34
zeroidc/vendor/tokio/src/loom/std/atomic_ptr.rs
vendored
|
@ -1,34 +0,0 @@
|
|||
use std::fmt;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// `AtomicPtr` providing an additional `load_unsync` function.
|
||||
pub(crate) struct AtomicPtr<T> {
|
||||
inner: std::sync::atomic::AtomicPtr<T>,
|
||||
}
|
||||
|
||||
impl<T> AtomicPtr<T> {
|
||||
pub(crate) fn new(ptr: *mut T) -> AtomicPtr<T> {
|
||||
let inner = std::sync::atomic::AtomicPtr::new(ptr);
|
||||
AtomicPtr { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for AtomicPtr<T> {
|
||||
type Target = std::sync::atomic::AtomicPtr<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for AtomicPtr<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for AtomicPtr<T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.deref().fmt(fmt)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ use std::cell::UnsafeCell;
|
|||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// `AtomicU16` providing an additional `load_unsync` function.
|
||||
/// `AtomicU16` providing an additional `unsync_load` function.
|
||||
pub(crate) struct AtomicU16 {
|
||||
inner: UnsafeCell<std::sync::atomic::AtomicU16>,
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ impl AtomicU16 {
|
|||
/// All mutations must have happened before the unsynchronized load.
|
||||
/// Additionally, there must be no concurrent mutations.
|
||||
pub(crate) unsafe fn unsync_load(&self) -> u16 {
|
||||
*(*self.inner.get()).get_mut()
|
||||
core::ptr::read(self.inner.get() as *const u16)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
12
zeroidc/vendor/tokio/src/loom/std/atomic_u32.rs
vendored
12
zeroidc/vendor/tokio/src/loom/std/atomic_u32.rs
vendored
|
@ -2,7 +2,7 @@ use std::cell::UnsafeCell;
|
|||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// `AtomicU32` providing an additional `load_unsync` function.
|
||||
/// `AtomicU32` providing an additional `unsync_load` function.
|
||||
pub(crate) struct AtomicU32 {
|
||||
inner: UnsafeCell<std::sync::atomic::AtomicU32>,
|
||||
}
|
||||
|
@ -15,6 +15,16 @@ impl AtomicU32 {
|
|||
let inner = UnsafeCell::new(std::sync::atomic::AtomicU32::new(val));
|
||||
AtomicU32 { inner }
|
||||
}
|
||||
|
||||
/// Performs an unsynchronized load.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// All mutations must have happened before the unsynchronized load.
|
||||
/// Additionally, there must be no concurrent mutations.
|
||||
pub(crate) unsafe fn unsync_load(&self) -> u32 {
|
||||
core::ptr::read(self.inner.get() as *const u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AtomicU32 {
|
||||
|
|
79
zeroidc/vendor/tokio/src/loom/std/atomic_u64.rs
vendored
79
zeroidc/vendor/tokio/src/loom/std/atomic_u64.rs
vendored
|
@ -7,80 +7,13 @@
|
|||
// `#[cfg(target_has_atomic = "64")]`.
|
||||
// Refs: https://github.com/rust-lang/rust/tree/master/src/librustc_target
|
||||
cfg_has_atomic_u64! {
|
||||
pub(crate) use std::sync::atomic::AtomicU64;
|
||||
#[path = "atomic_u64_native.rs"]
|
||||
mod imp;
|
||||
}
|
||||
|
||||
cfg_not_has_atomic_u64! {
|
||||
use crate::loom::sync::Mutex;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct AtomicU64 {
|
||||
inner: Mutex<u64>,
|
||||
}
|
||||
|
||||
impl AtomicU64 {
|
||||
pub(crate) fn new(val: u64) -> Self {
|
||||
Self {
|
||||
inner: Mutex::new(val),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load(&self, _: Ordering) -> u64 {
|
||||
*self.inner.lock()
|
||||
}
|
||||
|
||||
pub(crate) fn store(&self, val: u64, _: Ordering) {
|
||||
*self.inner.lock() = val;
|
||||
}
|
||||
|
||||
pub(crate) fn fetch_add(&self, val: u64, _: Ordering) -> u64 {
|
||||
let mut lock = self.inner.lock();
|
||||
let prev = *lock;
|
||||
*lock = prev + val;
|
||||
prev
|
||||
}
|
||||
|
||||
pub(crate) fn fetch_or(&self, val: u64, _: Ordering) -> u64 {
|
||||
let mut lock = self.inner.lock();
|
||||
let prev = *lock;
|
||||
*lock = prev | val;
|
||||
prev
|
||||
}
|
||||
|
||||
pub(crate) fn compare_exchange(
|
||||
&self,
|
||||
current: u64,
|
||||
new: u64,
|
||||
_success: Ordering,
|
||||
_failure: Ordering,
|
||||
) -> Result<u64, u64> {
|
||||
let mut lock = self.inner.lock();
|
||||
|
||||
if *lock == current {
|
||||
*lock = new;
|
||||
Ok(current)
|
||||
} else {
|
||||
Err(*lock)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn compare_exchange_weak(
|
||||
&self,
|
||||
current: u64,
|
||||
new: u64,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<u64, u64> {
|
||||
self.compare_exchange(current, new, success, failure)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AtomicU64 {
|
||||
fn default() -> AtomicU64 {
|
||||
Self {
|
||||
inner: Mutex::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[path = "atomic_u64_as_mutex.rs"]
|
||||
mod imp;
|
||||
}
|
||||
|
||||
pub(crate) use imp::{AtomicU64, StaticAtomicU64};
|
||||
|
|
76
zeroidc/vendor/tokio/src/loom/std/atomic_u64_as_mutex.rs
vendored
Normal file
76
zeroidc/vendor/tokio/src/loom/std/atomic_u64_as_mutex.rs
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
use crate::loom::sync::Mutex;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
cfg_has_const_mutex_new! {
|
||||
#[path = "atomic_u64_static_const_new.rs"]
|
||||
mod static_macro;
|
||||
}
|
||||
|
||||
cfg_not_has_const_mutex_new! {
|
||||
#[path = "atomic_u64_static_once_cell.rs"]
|
||||
mod static_macro;
|
||||
}
|
||||
|
||||
pub(crate) use static_macro::StaticAtomicU64;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct AtomicU64 {
|
||||
inner: Mutex<u64>,
|
||||
}
|
||||
|
||||
impl AtomicU64 {
|
||||
pub(crate) fn load(&self, _: Ordering) -> u64 {
|
||||
*self.inner.lock()
|
||||
}
|
||||
|
||||
pub(crate) fn store(&self, val: u64, _: Ordering) {
|
||||
*self.inner.lock() = val;
|
||||
}
|
||||
|
||||
pub(crate) fn fetch_add(&self, val: u64, _: Ordering) -> u64 {
|
||||
let mut lock = self.inner.lock();
|
||||
let prev = *lock;
|
||||
*lock = prev + val;
|
||||
prev
|
||||
}
|
||||
|
||||
pub(crate) fn fetch_or(&self, val: u64, _: Ordering) -> u64 {
|
||||
let mut lock = self.inner.lock();
|
||||
let prev = *lock;
|
||||
*lock = prev | val;
|
||||
prev
|
||||
}
|
||||
|
||||
pub(crate) fn compare_exchange(
|
||||
&self,
|
||||
current: u64,
|
||||
new: u64,
|
||||
_success: Ordering,
|
||||
_failure: Ordering,
|
||||
) -> Result<u64, u64> {
|
||||
let mut lock = self.inner.lock();
|
||||
|
||||
if *lock == current {
|
||||
*lock = new;
|
||||
Ok(current)
|
||||
} else {
|
||||
Err(*lock)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn compare_exchange_weak(
|
||||
&self,
|
||||
current: u64,
|
||||
new: u64,
|
||||
success: Ordering,
|
||||
failure: Ordering,
|
||||
) -> Result<u64, u64> {
|
||||
self.compare_exchange(current, new, success, failure)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AtomicU64 {
|
||||
fn default() -> AtomicU64 {
|
||||
AtomicU64::new(u64::default())
|
||||
}
|
||||
}
|
4
zeroidc/vendor/tokio/src/loom/std/atomic_u64_native.rs
vendored
Normal file
4
zeroidc/vendor/tokio/src/loom/std/atomic_u64_native.rs
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
pub(crate) use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
/// Alias `AtomicU64` to `StaticAtomicU64`
|
||||
pub(crate) type StaticAtomicU64 = AtomicU64;
|
12
zeroidc/vendor/tokio/src/loom/std/atomic_u64_static_const_new.rs
vendored
Normal file
12
zeroidc/vendor/tokio/src/loom/std/atomic_u64_static_const_new.rs
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
use super::AtomicU64;
|
||||
use crate::loom::sync::Mutex;
|
||||
|
||||
pub(crate) type StaticAtomicU64 = AtomicU64;
|
||||
|
||||
impl AtomicU64 {
|
||||
pub(crate) const fn new(val: u64) -> Self {
|
||||
Self {
|
||||
inner: Mutex::const_new(val),
|
||||
}
|
||||
}
|
||||
}
|
57
zeroidc/vendor/tokio/src/loom/std/atomic_u64_static_once_cell.rs
vendored
Normal file
57
zeroidc/vendor/tokio/src/loom/std/atomic_u64_static_once_cell.rs
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
use super::AtomicU64;
|
||||
use crate::loom::sync::{atomic::Ordering, Mutex};
|
||||
use crate::util::once_cell::OnceCell;
|
||||
|
||||
pub(crate) struct StaticAtomicU64 {
|
||||
init: u64,
|
||||
cell: OnceCell<Mutex<u64>>,
|
||||
}
|
||||
|
||||
impl AtomicU64 {
|
||||
pub(crate) fn new(val: u64) -> Self {
|
||||
Self {
|
||||
inner: Mutex::new(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StaticAtomicU64 {
|
||||
pub(crate) const fn new(val: u64) -> StaticAtomicU64 {
|
||||
StaticAtomicU64 {
|
||||
init: val,
|
||||
cell: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load(&self, order: Ordering) -> u64 {
|
||||
*self.inner().lock()
|
||||
}
|
||||
|
||||
pub(crate) fn fetch_add(&self, val: u64, order: Ordering) -> u64 {
|
||||
let mut lock = self.inner().lock();
|
||||
let prev = *lock;
|
||||
*lock = prev + val;
|
||||
prev
|
||||
}
|
||||
|
||||
pub(crate) fn compare_exchange_weak(
|
||||
&self,
|
||||
current: u64,
|
||||
new: u64,
|
||||
_success: Ordering,
|
||||
_failure: Ordering,
|
||||
) -> Result<u64, u64> {
|
||||
let mut lock = self.inner().lock();
|
||||
|
||||
if *lock == current {
|
||||
*lock = new;
|
||||
Ok(current)
|
||||
} else {
|
||||
Err(*lock)
|
||||
}
|
||||
}
|
||||
|
||||
fn inner(&self) -> &Mutex<u64> {
|
||||
self.cell.get(|| Mutex::new(self.init))
|
||||
}
|
||||
}
|
34
zeroidc/vendor/tokio/src/loom/std/atomic_u8.rs
vendored
34
zeroidc/vendor/tokio/src/loom/std/atomic_u8.rs
vendored
|
@ -1,34 +0,0 @@
|
|||
use std::cell::UnsafeCell;
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// `AtomicU8` providing an additional `load_unsync` function.
|
||||
pub(crate) struct AtomicU8 {
|
||||
inner: UnsafeCell<std::sync::atomic::AtomicU8>,
|
||||
}
|
||||
|
||||
unsafe impl Send for AtomicU8 {}
|
||||
unsafe impl Sync for AtomicU8 {}
|
||||
|
||||
impl AtomicU8 {
|
||||
pub(crate) const fn new(val: u8) -> AtomicU8 {
|
||||
let inner = UnsafeCell::new(std::sync::atomic::AtomicU8::new(val));
|
||||
AtomicU8 { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AtomicU8 {
|
||||
type Target = std::sync::atomic::AtomicU8;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// safety: it is always safe to access `&self` fns on the inner value as
|
||||
// we never perform unsafe mutations.
|
||||
unsafe { &*self.inner.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for AtomicU8 {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.deref().fmt(fmt)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ use std::cell::UnsafeCell;
|
|||
use std::fmt;
|
||||
use std::ops;
|
||||
|
||||
/// `AtomicUsize` providing an additional `load_unsync` function.
|
||||
/// `AtomicUsize` providing an additional `unsync_load` function.
|
||||
pub(crate) struct AtomicUsize {
|
||||
inner: UnsafeCell<std::sync::atomic::AtomicUsize>,
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ impl AtomicUsize {
|
|||
/// All mutations must have happened before the unsynchronized load.
|
||||
/// Additionally, there must be no concurrent mutations.
|
||||
pub(crate) unsafe fn unsync_load(&self) -> usize {
|
||||
*(*self.inner.get()).get_mut()
|
||||
core::ptr::read(self.inner.get() as *const usize)
|
||||
}
|
||||
|
||||
pub(crate) fn with_mut<R>(&mut self, f: impl FnOnce(&mut usize) -> R) -> R {
|
||||
|
|
34
zeroidc/vendor/tokio/src/loom/std/mod.rs
vendored
34
zeroidc/vendor/tokio/src/loom/std/mod.rs
vendored
|
@ -1,10 +1,8 @@
|
|||
#![cfg_attr(any(not(feature = "full"), loom), allow(unused_imports, dead_code))]
|
||||
|
||||
mod atomic_ptr;
|
||||
mod atomic_u16;
|
||||
mod atomic_u32;
|
||||
mod atomic_u64;
|
||||
mod atomic_u8;
|
||||
mod atomic_usize;
|
||||
mod mutex;
|
||||
#[cfg(feature = "parking_lot")]
|
||||
|
@ -71,21 +69,39 @@ pub(crate) mod sync {
|
|||
pub(crate) use crate::loom::std::mutex::Mutex;
|
||||
|
||||
pub(crate) mod atomic {
|
||||
pub(crate) use crate::loom::std::atomic_ptr::AtomicPtr;
|
||||
pub(crate) use crate::loom::std::atomic_u16::AtomicU16;
|
||||
pub(crate) use crate::loom::std::atomic_u32::AtomicU32;
|
||||
pub(crate) use crate::loom::std::atomic_u64::AtomicU64;
|
||||
pub(crate) use crate::loom::std::atomic_u8::AtomicU8;
|
||||
pub(crate) use crate::loom::std::atomic_u64::{AtomicU64, StaticAtomicU64};
|
||||
pub(crate) use crate::loom::std::atomic_usize::AtomicUsize;
|
||||
|
||||
pub(crate) use std::sync::atomic::{fence, AtomicBool, Ordering};
|
||||
pub(crate) use std::sync::atomic::{fence, AtomicBool, AtomicPtr, AtomicU8, Ordering};
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sys {
|
||||
#[cfg(feature = "rt-multi-thread")]
|
||||
pub(crate) fn num_cpus() -> usize {
|
||||
usize::max(1, num_cpus::get())
|
||||
const ENV_WORKER_THREADS: &str = "TOKIO_WORKER_THREADS";
|
||||
|
||||
match std::env::var(ENV_WORKER_THREADS) {
|
||||
Ok(s) => {
|
||||
let n = s.parse().unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"\"{}\" must be usize, error: {}, value: {}",
|
||||
ENV_WORKER_THREADS, e, s
|
||||
)
|
||||
});
|
||||
assert!(n > 0, "\"{}\" cannot be set to 0", ENV_WORKER_THREADS);
|
||||
n
|
||||
}
|
||||
Err(std::env::VarError::NotPresent) => usize::max(1, num_cpus::get()),
|
||||
Err(std::env::VarError::NotUnicode(e)) => {
|
||||
panic!(
|
||||
"\"{}\" must be valid unicode, error: {:?}",
|
||||
ENV_WORKER_THREADS, e
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rt-multi-thread"))]
|
||||
|
@ -102,7 +118,7 @@ pub(crate) mod thread {
|
|||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use std::thread::{
|
||||
current, panicking, park, park_timeout, sleep, spawn, Builder, JoinHandle, LocalKey,
|
||||
Result, Thread, ThreadId,
|
||||
current, panicking, park, park_timeout, sleep, spawn, AccessError, Builder, JoinHandle,
|
||||
LocalKey, Result, Thread, ThreadId,
|
||||
};
|
||||
}
|
||||
|
|
6
zeroidc/vendor/tokio/src/loom/std/mutex.rs
vendored
6
zeroidc/vendor/tokio/src/loom/std/mutex.rs
vendored
|
@ -12,6 +12,12 @@ impl<T> Mutex<T> {
|
|||
Mutex(sync::Mutex::new(t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(tokio_no_const_mutex_new))]
|
||||
pub(crate) const fn const_new(t: T) -> Mutex<T> {
|
||||
Mutex(sync::Mutex::new(t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn lock(&self) -> MutexGuard<'_, T> {
|
||||
match self.0.lock() {
|
||||
|
|
|
@ -52,7 +52,7 @@ impl<T> Mutex<T> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(all(feature = "parking_lot", not(all(loom, test)),))]
|
||||
#[cfg(all(feature = "parking_lot", not(all(loom, test))))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "parking_lot",))))]
|
||||
pub(crate) const fn const_new(t: T) -> Mutex<T> {
|
||||
Mutex(PhantomData, parking_lot::const_mutex(t))
|
||||
|
|
53
zeroidc/vendor/tokio/src/macros/addr_of.rs
vendored
Normal file
53
zeroidc/vendor/tokio/src/macros/addr_of.rs
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
//! This module defines a macro that lets you go from a raw pointer to a struct
|
||||
//! to a raw pointer to a field of the struct.
|
||||
|
||||
#[cfg(not(tokio_no_addr_of))]
|
||||
macro_rules! generate_addr_of_methods {
|
||||
(
|
||||
impl<$($gen:ident)*> $struct_name:ty {$(
|
||||
$(#[$attrs:meta])*
|
||||
$vis:vis unsafe fn $fn_name:ident(self: NonNull<Self>) -> NonNull<$field_type:ty> {
|
||||
&self$(.$field_name:tt)+
|
||||
}
|
||||
)*}
|
||||
) => {
|
||||
impl<$($gen)*> $struct_name {$(
|
||||
$(#[$attrs])*
|
||||
$vis unsafe fn $fn_name(me: ::core::ptr::NonNull<Self>) -> ::core::ptr::NonNull<$field_type> {
|
||||
let me = me.as_ptr();
|
||||
let field = ::std::ptr::addr_of_mut!((*me) $(.$field_name)+ );
|
||||
::core::ptr::NonNull::new_unchecked(field)
|
||||
}
|
||||
)*}
|
||||
};
|
||||
}
|
||||
|
||||
// The `addr_of_mut!` macro is only available for MSRV at least 1.51.0. This
|
||||
// version of the macro uses a workaround for older versions of rustc.
|
||||
#[cfg(tokio_no_addr_of)]
|
||||
macro_rules! generate_addr_of_methods {
|
||||
(
|
||||
impl<$($gen:ident)*> $struct_name:ty {$(
|
||||
$(#[$attrs:meta])*
|
||||
$vis:vis unsafe fn $fn_name:ident(self: NonNull<Self>) -> NonNull<$field_type:ty> {
|
||||
&self$(.$field_name:tt)+
|
||||
}
|
||||
)*}
|
||||
) => {
|
||||
impl<$($gen)*> $struct_name {$(
|
||||
$(#[$attrs])*
|
||||
$vis unsafe fn $fn_name(me: ::core::ptr::NonNull<Self>) -> ::core::ptr::NonNull<$field_type> {
|
||||
let me = me.as_ptr();
|
||||
let me_u8 = me as *mut u8;
|
||||
|
||||
let field_offset = {
|
||||
let me_ref = &*me;
|
||||
let field_ref_u8 = (&me_ref $(.$field_name)+ ) as *const $field_type as *const u8;
|
||||
field_ref_u8.offset_from(me_u8)
|
||||
};
|
||||
|
||||
::core::ptr::NonNull::new_unchecked(me_u8.offset(field_offset).cast())
|
||||
}
|
||||
)*}
|
||||
};
|
||||
}
|
102
zeroidc/vendor/tokio/src/macros/cfg.rs
vendored
102
zeroidc/vendor/tokio/src/macros/cfg.rs
vendored
|
@ -61,6 +61,7 @@ macro_rules! cfg_fs {
|
|||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(feature = "fs")]
|
||||
#[cfg(not(tokio_wasi))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
|
||||
$item
|
||||
)*
|
||||
|
@ -69,7 +70,11 @@ macro_rules! cfg_fs {
|
|||
|
||||
macro_rules! cfg_io_blocking {
|
||||
($($item:item)*) => {
|
||||
$( #[cfg(any(feature = "io-std", feature = "fs"))] $item )*
|
||||
$( #[cfg(any(
|
||||
feature = "io-std",
|
||||
feature = "fs",
|
||||
all(windows, feature = "process"),
|
||||
))] $item )*
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,12 +83,12 @@ macro_rules! cfg_io_driver {
|
|||
$(
|
||||
#[cfg(any(
|
||||
feature = "net",
|
||||
feature = "process",
|
||||
all(unix, feature = "process"),
|
||||
all(unix, feature = "signal"),
|
||||
))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(
|
||||
feature = "net",
|
||||
feature = "process",
|
||||
all(unix, feature = "process"),
|
||||
all(unix, feature = "signal"),
|
||||
))))]
|
||||
$item
|
||||
|
@ -96,7 +101,7 @@ macro_rules! cfg_io_driver_impl {
|
|||
$(
|
||||
#[cfg(any(
|
||||
feature = "net",
|
||||
feature = "process",
|
||||
all(unix, feature = "process"),
|
||||
all(unix, feature = "signal"),
|
||||
))]
|
||||
$item
|
||||
|
@ -109,7 +114,7 @@ macro_rules! cfg_not_io_driver {
|
|||
$(
|
||||
#[cfg(not(any(
|
||||
feature = "net",
|
||||
feature = "process",
|
||||
all(unix, feature = "process"),
|
||||
all(unix, feature = "signal"),
|
||||
)))]
|
||||
$item
|
||||
|
@ -247,6 +252,7 @@ macro_rules! cfg_process {
|
|||
#[cfg(feature = "process")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
|
||||
#[cfg(not(loom))]
|
||||
#[cfg(not(tokio_wasi))]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
|
@ -275,6 +281,7 @@ macro_rules! cfg_signal {
|
|||
#[cfg(feature = "signal")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
|
||||
#[cfg(not(loom))]
|
||||
#[cfg(not(tokio_wasi))]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
|
@ -290,6 +297,13 @@ macro_rules! cfg_signal_internal {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! cfg_signal_internal_and_unix {
|
||||
($($item:item)*) => {
|
||||
#[cfg(unix)]
|
||||
cfg_signal_internal! { $($item)* }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cfg_not_signal_internal {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
|
@ -334,7 +348,7 @@ macro_rules! cfg_not_rt {
|
|||
macro_rules! cfg_rt_multi_thread {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(feature = "rt-multi-thread")]
|
||||
#[cfg(all(feature = "rt-multi-thread", not(tokio_wasi)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
|
||||
$item
|
||||
)*
|
||||
|
@ -447,12 +461,14 @@ macro_rules! cfg_not_coop {
|
|||
macro_rules! cfg_has_atomic_u64 {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(not(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "mips",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "riscv32"
|
||||
)))]
|
||||
#[cfg_attr(
|
||||
not(tokio_no_target_has_atomic),
|
||||
cfg(all(target_has_atomic = "64", not(tokio_no_atomic_u64))
|
||||
))]
|
||||
#[cfg_attr(
|
||||
tokio_no_target_has_atomic,
|
||||
cfg(not(tokio_no_atomic_u64))
|
||||
)]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
|
@ -461,12 +477,62 @@ macro_rules! cfg_has_atomic_u64 {
|
|||
macro_rules! cfg_not_has_atomic_u64 {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "mips",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "riscv32"
|
||||
))]
|
||||
#[cfg_attr(
|
||||
not(tokio_no_target_has_atomic),
|
||||
cfg(any(not(target_has_atomic = "64"), tokio_no_atomic_u64)
|
||||
))]
|
||||
#[cfg_attr(
|
||||
tokio_no_target_has_atomic,
|
||||
cfg(tokio_no_atomic_u64)
|
||||
)]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cfg_has_const_mutex_new {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(all(
|
||||
not(all(loom, test)),
|
||||
any(
|
||||
feature = "parking_lot",
|
||||
not(tokio_no_const_mutex_new)
|
||||
)
|
||||
))]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cfg_not_has_const_mutex_new {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(not(all(
|
||||
not(all(loom, test)),
|
||||
any(
|
||||
feature = "parking_lot",
|
||||
not(tokio_no_const_mutex_new)
|
||||
)
|
||||
)))]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cfg_not_wasi {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(not(tokio_wasi))]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cfg_is_wasm_not_wasi {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(tokio_wasm_not_wasi)]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
|
|
12
zeroidc/vendor/tokio/src/macros/join.rs
vendored
12
zeroidc/vendor/tokio/src/macros/join.rs
vendored
|
@ -72,8 +72,18 @@ macro_rules! join {
|
|||
|
||||
// Safety: nothing must be moved out of `futures`. This is to satisfy
|
||||
// the requirement of `Pin::new_unchecked` called below.
|
||||
//
|
||||
// We can't use the `pin!` macro for this because `futures` is a tuple
|
||||
// and the standard library provides no way to pin-project to the fields
|
||||
// of a tuple.
|
||||
let mut futures = ( $( maybe_done($e), )* );
|
||||
|
||||
// This assignment makes sure that the `poll_fn` closure only has a
|
||||
// reference to the futures, instead of taking ownership of them. This
|
||||
// mitigates the issue described in
|
||||
// <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
|
||||
let mut futures = &mut futures;
|
||||
|
||||
// Each time the future created by poll_fn is polled, a different future will be polled first
|
||||
// to ensure every future passed to join! gets a chance to make progress even if
|
||||
// one of the futures consumes the whole budget.
|
||||
|
@ -106,7 +116,7 @@ macro_rules! join {
|
|||
to_run -= 1;
|
||||
|
||||
// Extract the future for this branch from the tuple.
|
||||
let ( $($skip,)* fut, .. ) = &mut futures;
|
||||
let ( $($skip,)* fut, .. ) = &mut *futures;
|
||||
|
||||
// Safety: future is stored on the stack above
|
||||
// and never moved.
|
||||
|
|
3
zeroidc/vendor/tokio/src/macros/mod.rs
vendored
3
zeroidc/vendor/tokio/src/macros/mod.rs
vendored
|
@ -15,6 +15,9 @@ mod ready;
|
|||
#[macro_use]
|
||||
mod thread_local;
|
||||
|
||||
#[macro_use]
|
||||
mod addr_of;
|
||||
|
||||
cfg_trace! {
|
||||
#[macro_use]
|
||||
mod trace;
|
||||
|
|
|
@ -10,7 +10,7 @@ macro_rules! scoped_thread_local {
|
|||
$vis static $name: $crate::macros::scoped_tls::ScopedKey<$ty>
|
||||
= $crate::macros::scoped_tls::ScopedKey {
|
||||
inner: {
|
||||
thread_local!(static FOO: ::std::cell::Cell<*const ()> = {
|
||||
tokio_thread_local!(static FOO: ::std::cell::Cell<*const ()> = const {
|
||||
std::cell::Cell::new(::std::ptr::null())
|
||||
});
|
||||
&FOO
|
||||
|
|
12
zeroidc/vendor/tokio/src/macros/select.rs
vendored
12
zeroidc/vendor/tokio/src/macros/select.rs
vendored
|
@ -460,8 +460,18 @@ macro_rules! select {
|
|||
let mut output = {
|
||||
// Safety: Nothing must be moved out of `futures`. This is to
|
||||
// satisfy the requirement of `Pin::new_unchecked` called below.
|
||||
//
|
||||
// We can't use the `pin!` macro for this because `futures` is a
|
||||
// tuple and the standard library provides no way to pin-project to
|
||||
// the fields of a tuple.
|
||||
let mut futures = ( $( $fut , )+ );
|
||||
|
||||
// This assignment makes sure that the `poll_fn` closure only has a
|
||||
// reference to the futures, instead of taking ownership of them.
|
||||
// This mitigates the issue described in
|
||||
// <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
|
||||
let mut futures = &mut futures;
|
||||
|
||||
$crate::macros::support::poll_fn(|cx| {
|
||||
// Track if any branch returns pending. If no branch completes
|
||||
// **or** returns pending, this implies that all branches are
|
||||
|
@ -497,7 +507,7 @@ macro_rules! select {
|
|||
|
||||
// Extract the future for this branch from the
|
||||
// tuple
|
||||
let ( $($skip,)* fut, .. ) = &mut futures;
|
||||
let ( $($skip,)* fut, .. ) = &mut *futures;
|
||||
|
||||
// Safety: future is stored on the stack above
|
||||
// and never moved.
|
||||
|
|
6
zeroidc/vendor/tokio/src/macros/support.rs
vendored
6
zeroidc/vendor/tokio/src/macros/support.rs
vendored
|
@ -1,7 +1,11 @@
|
|||
cfg_macros! {
|
||||
pub use crate::future::poll_fn;
|
||||
pub use crate::future::maybe_done::maybe_done;
|
||||
pub use crate::util::thread_rng_n;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn thread_rng_n(n: u32) -> u32 {
|
||||
crate::runtime::context::thread_rng_n(n)
|
||||
}
|
||||
}
|
||||
|
||||
pub use std::future::Future;
|
||||
|
|
30
zeroidc/vendor/tokio/src/macros/thread_local.rs
vendored
30
zeroidc/vendor/tokio/src/macros/thread_local.rs
vendored
|
@ -1,4 +1,32 @@
|
|||
#[cfg(all(loom, test))]
|
||||
macro_rules! thread_local {
|
||||
macro_rules! tokio_thread_local {
|
||||
($(#[$attrs:meta])* $vis:vis static $name:ident: $ty:ty = const { $expr:expr } $(;)?) => {
|
||||
loom::thread_local! {
|
||||
$(#[$attrs])*
|
||||
$vis static $name: $ty = $expr;
|
||||
}
|
||||
};
|
||||
|
||||
($($tts:tt)+) => { loom::thread_local!{ $($tts)+ } }
|
||||
}
|
||||
|
||||
#[cfg(not(tokio_no_const_thread_local))]
|
||||
#[cfg(not(all(loom, test)))]
|
||||
macro_rules! tokio_thread_local {
|
||||
($($tts:tt)+) => {
|
||||
::std::thread_local!{ $($tts)+ }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(tokio_no_const_thread_local)]
|
||||
#[cfg(not(all(loom, test)))]
|
||||
macro_rules! tokio_thread_local {
|
||||
($(#[$attrs:meta])* $vis:vis static $name:ident: $ty:ty = const { $expr:expr } $(;)?) => {
|
||||
::std::thread_local! {
|
||||
$(#[$attrs])*
|
||||
$vis static $name: $ty = $expr;
|
||||
}
|
||||
};
|
||||
|
||||
($($tts:tt)+) => { ::std::thread_local!{ $($tts)+ } }
|
||||
}
|
||||
|
|
12
zeroidc/vendor/tokio/src/macros/try_join.rs
vendored
12
zeroidc/vendor/tokio/src/macros/try_join.rs
vendored
|
@ -118,8 +118,18 @@ macro_rules! try_join {
|
|||
|
||||
// Safety: nothing must be moved out of `futures`. This is to satisfy
|
||||
// the requirement of `Pin::new_unchecked` called below.
|
||||
//
|
||||
// We can't use the `pin!` macro for this because `futures` is a tuple
|
||||
// and the standard library provides no way to pin-project to the fields
|
||||
// of a tuple.
|
||||
let mut futures = ( $( maybe_done($e), )* );
|
||||
|
||||
// This assignment makes sure that the `poll_fn` closure only has a
|
||||
// reference to the futures, instead of taking ownership of them. This
|
||||
// mitigates the issue described in
|
||||
// <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
|
||||
let mut futures = &mut futures;
|
||||
|
||||
// Each time the future created by poll_fn is polled, a different future will be polled first
|
||||
// to ensure every future passed to join! gets a chance to make progress even if
|
||||
// one of the futures consumes the whole budget.
|
||||
|
@ -152,7 +162,7 @@ macro_rules! try_join {
|
|||
to_run -= 1;
|
||||
|
||||
// Extract the future for this branch from the tuple.
|
||||
let ( $($skip,)* fut, .. ) = &mut futures;
|
||||
let ( $($skip,)* fut, .. ) = &mut *futures;
|
||||
|
||||
// Safety: future is stored on the stack above
|
||||
// and never moved.
|
||||
|
|
2
zeroidc/vendor/tokio/src/net/addr.rs
vendored
2
zeroidc/vendor/tokio/src/net/addr.rs
vendored
|
@ -244,7 +244,7 @@ cfg_net! {
|
|||
type Future = <str as sealed::ToSocketAddrsPriv>::Future;
|
||||
|
||||
fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
|
||||
(&self[..]).to_socket_addrs(sealed::Internal)
|
||||
self[..].to_socket_addrs(sealed::Internal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
14
zeroidc/vendor/tokio/src/net/mod.rs
vendored
14
zeroidc/vendor/tokio/src/net/mod.rs
vendored
|
@ -23,8 +23,10 @@
|
|||
//! [`UnixDatagram`]: UnixDatagram
|
||||
|
||||
mod addr;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) use addr::to_socket_addrs;
|
||||
cfg_not_wasi! {
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) use addr::to_socket_addrs;
|
||||
}
|
||||
pub use addr::ToSocketAddrs;
|
||||
|
||||
cfg_net! {
|
||||
|
@ -33,11 +35,13 @@ cfg_net! {
|
|||
|
||||
pub mod tcp;
|
||||
pub use tcp::listener::TcpListener;
|
||||
pub use tcp::socket::TcpSocket;
|
||||
pub use tcp::stream::TcpStream;
|
||||
cfg_not_wasi! {
|
||||
pub use tcp::socket::TcpSocket;
|
||||
|
||||
mod udp;
|
||||
pub use udp::UdpSocket;
|
||||
mod udp;
|
||||
pub use udp::UdpSocket;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_net_unix! {
|
||||
|
|
156
zeroidc/vendor/tokio/src/net/tcp/listener.rs
vendored
156
zeroidc/vendor/tokio/src/net/tcp/listener.rs
vendored
|
@ -1,6 +1,9 @@
|
|||
use crate::io::{Interest, PollEvented};
|
||||
use crate::net::tcp::TcpStream;
|
||||
use crate::net::{to_socket_addrs, ToSocketAddrs};
|
||||
|
||||
cfg_not_wasi! {
|
||||
use crate::net::{to_socket_addrs, ToSocketAddrs};
|
||||
}
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
|
@ -55,68 +58,70 @@ cfg_net! {
|
|||
}
|
||||
|
||||
impl TcpListener {
|
||||
/// Creates a new TcpListener, which will be bound to the specified address.
|
||||
///
|
||||
/// The returned listener is ready for accepting connections.
|
||||
///
|
||||
/// Binding with a port number of 0 will request that the OS assigns a port
|
||||
/// to this listener. The port allocated can be queried via the `local_addr`
|
||||
/// method.
|
||||
///
|
||||
/// The address type can be any implementor of the [`ToSocketAddrs`] trait.
|
||||
/// If `addr` yields multiple addresses, bind will be attempted with each of
|
||||
/// the addresses until one succeeds and returns the listener. If none of
|
||||
/// the addresses succeed in creating a listener, the error returned from
|
||||
/// the last attempt (the last address) is returned.
|
||||
///
|
||||
/// This function sets the `SO_REUSEADDR` option on the socket.
|
||||
///
|
||||
/// To configure the socket before binding, you can use the [`TcpSocket`]
|
||||
/// type.
|
||||
///
|
||||
/// [`ToSocketAddrs`]: trait@crate::net::ToSocketAddrs
|
||||
/// [`TcpSocket`]: struct@crate::net::TcpSocket
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpListener;
|
||||
///
|
||||
/// use std::io;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let listener = TcpListener::bind("127.0.0.1:2345").await?;
|
||||
///
|
||||
/// // use the listener
|
||||
///
|
||||
/// # let _ = listener;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||
let addrs = to_socket_addrs(addr).await?;
|
||||
cfg_not_wasi! {
|
||||
/// Creates a new TcpListener, which will be bound to the specified address.
|
||||
///
|
||||
/// The returned listener is ready for accepting connections.
|
||||
///
|
||||
/// Binding with a port number of 0 will request that the OS assigns a port
|
||||
/// to this listener. The port allocated can be queried via the `local_addr`
|
||||
/// method.
|
||||
///
|
||||
/// The address type can be any implementor of the [`ToSocketAddrs`] trait.
|
||||
/// If `addr` yields multiple addresses, bind will be attempted with each of
|
||||
/// the addresses until one succeeds and returns the listener. If none of
|
||||
/// the addresses succeed in creating a listener, the error returned from
|
||||
/// the last attempt (the last address) is returned.
|
||||
///
|
||||
/// This function sets the `SO_REUSEADDR` option on the socket.
|
||||
///
|
||||
/// To configure the socket before binding, you can use the [`TcpSocket`]
|
||||
/// type.
|
||||
///
|
||||
/// [`ToSocketAddrs`]: trait@crate::net::ToSocketAddrs
|
||||
/// [`TcpSocket`]: struct@crate::net::TcpSocket
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpListener;
|
||||
///
|
||||
/// use std::io;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let listener = TcpListener::bind("127.0.0.1:2345").await?;
|
||||
///
|
||||
/// // use the listener
|
||||
///
|
||||
/// # let _ = listener;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||
let addrs = to_socket_addrs(addr).await?;
|
||||
|
||||
let mut last_err = None;
|
||||
let mut last_err = None;
|
||||
|
||||
for addr in addrs {
|
||||
match TcpListener::bind_addr(addr) {
|
||||
Ok(listener) => return Ok(listener),
|
||||
Err(e) => last_err = Some(e),
|
||||
for addr in addrs {
|
||||
match TcpListener::bind_addr(addr) {
|
||||
Ok(listener) => return Ok(listener),
|
||||
Err(e) => last_err = Some(e),
|
||||
}
|
||||
}
|
||||
|
||||
Err(last_err.unwrap_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"could not resolve to any address",
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
Err(last_err.unwrap_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"could not resolve to any address",
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
fn bind_addr(addr: SocketAddr) -> io::Result<TcpListener> {
|
||||
let listener = mio::net::TcpListener::bind(addr)?;
|
||||
TcpListener::new(listener)
|
||||
fn bind_addr(addr: SocketAddr) -> io::Result<TcpListener> {
|
||||
let listener = mio::net::TcpListener::bind(addr)?;
|
||||
TcpListener::new(listener)
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts a new incoming connection from this listener.
|
||||
|
@ -216,11 +221,13 @@ impl TcpListener {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if thread-local runtime is not set.
|
||||
/// This function panics if it is not called from within a runtime with
|
||||
/// IO enabled.
|
||||
///
|
||||
/// The runtime is usually set implicitly when this function is called
|
||||
/// from a future driven by a tokio runtime, otherwise runtime can be set
|
||||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
|
||||
#[track_caller]
|
||||
pub fn from_std(listener: net::TcpListener) -> io::Result<TcpListener> {
|
||||
let io = mio::net::TcpListener::from_std(listener);
|
||||
let io = PollEvented::new(io)?;
|
||||
|
@ -267,11 +274,22 @@ impl TcpListener {
|
|||
.map(|io| io.into_raw_socket())
|
||||
.map(|raw_socket| unsafe { std::net::TcpListener::from_raw_socket(raw_socket) })
|
||||
}
|
||||
|
||||
#[cfg(tokio_wasi)]
|
||||
{
|
||||
use std::os::wasi::io::{FromRawFd, IntoRawFd};
|
||||
self.io
|
||||
.into_inner()
|
||||
.map(|io| io.into_raw_fd())
|
||||
.map(|raw_fd| unsafe { std::net::TcpListener::from_raw_fd(raw_fd) })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new(listener: mio::net::TcpListener) -> io::Result<TcpListener> {
|
||||
let io = PollEvented::new(listener)?;
|
||||
Ok(TcpListener { io })
|
||||
cfg_not_wasi! {
|
||||
pub(crate) fn new(listener: mio::net::TcpListener) -> io::Result<TcpListener> {
|
||||
let io = PollEvented::new(listener)?;
|
||||
Ok(TcpListener { io })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the local address that this listener is bound to.
|
||||
|
@ -384,6 +402,20 @@ mod sys {
|
|||
}
|
||||
}
|
||||
|
||||
cfg_unstable! {
|
||||
#[cfg(tokio_wasi)]
|
||||
mod sys {
|
||||
use super::TcpListener;
|
||||
use std::os::wasi::prelude::*;
|
||||
|
||||
impl AsRawFd for TcpListener {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.io.as_raw_fd()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod sys {
|
||||
use super::TcpListener;
|
||||
|
|
4
zeroidc/vendor/tokio/src/net/tcp/mod.rs
vendored
4
zeroidc/vendor/tokio/src/net/tcp/mod.rs
vendored
|
@ -2,7 +2,9 @@
|
|||
|
||||
pub(crate) mod listener;
|
||||
|
||||
pub(crate) mod socket;
|
||||
cfg_not_wasi! {
|
||||
pub(crate) mod socket;
|
||||
}
|
||||
|
||||
mod split;
|
||||
pub use split::{ReadHalf, WriteHalf};
|
||||
|
|
83
zeroidc/vendor/tokio/src/net/tcp/socket.rs
vendored
83
zeroidc/vendor/tokio/src/net/tcp/socket.rs
vendored
|
@ -398,6 +398,89 @@ impl TcpSocket {
|
|||
self.inner.linger()
|
||||
}
|
||||
|
||||
/// Gets the value of the `IP_TOS` option for this socket.
|
||||
///
|
||||
/// For more information about this option, see [`set_tos`].
|
||||
///
|
||||
/// **NOTE:** On Windows, `IP_TOS` is only supported on [Windows 8+ or
|
||||
/// Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options)
|
||||
///
|
||||
/// [`set_tos`]: Self::set_tos
|
||||
// https://docs.rs/socket2/0.4.2/src/socket2/socket.rs.html#1178
|
||||
#[cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
)))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
))))
|
||||
)]
|
||||
pub fn tos(&self) -> io::Result<u32> {
|
||||
self.inner.tos()
|
||||
}
|
||||
|
||||
/// Sets the value for the `IP_TOS` option on this socket.
|
||||
///
|
||||
/// This value sets the type-of-service field that is used in every packet
|
||||
/// sent from this socket.
|
||||
///
|
||||
/// **NOTE:** On Windows, `IP_TOS` is only supported on [Windows 8+ or
|
||||
/// Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options)
|
||||
// https://docs.rs/socket2/0.4.2/src/socket2/socket.rs.html#1178
|
||||
#[cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
)))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
))))
|
||||
)]
|
||||
pub fn set_tos(&self, tos: u32) -> io::Result<()> {
|
||||
self.inner.set_tos(tos)
|
||||
}
|
||||
|
||||
/// Gets the value for the `SO_BINDTODEVICE` option on this socket
|
||||
///
|
||||
/// This value gets the socket binded device's interface name.
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",)))
|
||||
)]
|
||||
pub fn device(&self) -> io::Result<Option<Vec<u8>>> {
|
||||
self.inner.device()
|
||||
}
|
||||
|
||||
/// Sets the value for the `SO_BINDTODEVICE` option on this socket
|
||||
///
|
||||
/// If a socket is bound to an interface, only packets received from that
|
||||
/// particular interface are processed by the socket. Note that this only
|
||||
/// works for some socket types, particularly `AF_INET` sockets.
|
||||
///
|
||||
/// If `interface` is `None` or an empty string it removes the binding.
|
||||
#[cfg(all(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(all(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))))
|
||||
)]
|
||||
pub fn bind_device(&self, interface: Option<&[u8]>) -> io::Result<()> {
|
||||
self.inner.bind_device(interface)
|
||||
}
|
||||
|
||||
/// Gets the local address of this socket.
|
||||
///
|
||||
/// Will fail on windows if called before `bind`.
|
||||
|
|
20
zeroidc/vendor/tokio/src/net/tcp/split.rs
vendored
20
zeroidc/vendor/tokio/src/net/tcp/split.rs
vendored
|
@ -145,6 +145,12 @@ impl ReadHalf<'_> {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// This function is equivalent to [`TcpStream::ready`].
|
||||
///
|
||||
/// # Cancel safety
|
||||
|
@ -190,8 +196,12 @@ impl ReadHalf<'_> {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the stream's read half is closed
|
||||
/// and will no longer yield data. If the stream is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The stream's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the stream is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
pub fn try_read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.try_read(buf)
|
||||
|
@ -269,6 +279,12 @@ impl WriteHalf<'_> {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// This function is equivalent to [`TcpStream::ready`].
|
||||
///
|
||||
/// # Cancel safety
|
||||
|
|
24
zeroidc/vendor/tokio/src/net/tcp/split_owned.rs
vendored
24
zeroidc/vendor/tokio/src/net/tcp/split_owned.rs
vendored
|
@ -200,6 +200,12 @@ impl OwnedReadHalf {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// This function is equivalent to [`TcpStream::ready`].
|
||||
///
|
||||
/// # Cancel safety
|
||||
|
@ -245,8 +251,12 @@ impl OwnedReadHalf {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the stream's read half is closed
|
||||
/// and will no longer yield data. If the stream is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The stream's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the stream is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
pub fn try_read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.try_read(buf)
|
||||
|
@ -351,6 +361,12 @@ impl OwnedWriteHalf {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// This function is equivalent to [`TcpStream::ready`].
|
||||
///
|
||||
/// # Cancel safety
|
||||
|
@ -474,12 +490,12 @@ impl AsyncWrite for OwnedWriteHalf {
|
|||
|
||||
impl AsRef<TcpStream> for OwnedReadHalf {
|
||||
fn as_ref(&self) -> &TcpStream {
|
||||
&*self.inner
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<TcpStream> for OwnedWriteHalf {
|
||||
fn as_ref(&self) -> &TcpStream {
|
||||
&*self.inner
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
|
295
zeroidc/vendor/tokio/src/net/tcp/stream.rs
vendored
295
zeroidc/vendor/tokio/src/net/tcp/stream.rs
vendored
|
@ -1,8 +1,12 @@
|
|||
use crate::future::poll_fn;
|
||||
cfg_not_wasi! {
|
||||
use crate::future::poll_fn;
|
||||
use crate::net::{to_socket_addrs, ToSocketAddrs};
|
||||
use std::time::Duration;
|
||||
}
|
||||
|
||||
use crate::io::{AsyncRead, AsyncWrite, Interest, PollEvented, ReadBuf, Ready};
|
||||
use crate::net::tcp::split::{split, ReadHalf, WriteHalf};
|
||||
use crate::net::tcp::split_owned::{split_owned, OwnedReadHalf, OwnedWriteHalf};
|
||||
use crate::net::{to_socket_addrs, ToSocketAddrs};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
|
@ -10,7 +14,6 @@ use std::io;
|
|||
use std::net::{Shutdown, SocketAddr};
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::time::Duration;
|
||||
|
||||
cfg_io_util! {
|
||||
use bytes::BufMut;
|
||||
|
@ -70,86 +73,88 @@ cfg_net! {
|
|||
}
|
||||
|
||||
impl TcpStream {
|
||||
/// Opens a TCP connection to a remote host.
|
||||
///
|
||||
/// `addr` is an address of the remote host. Anything which implements the
|
||||
/// [`ToSocketAddrs`] trait can be supplied as the address. If `addr`
|
||||
/// yields multiple addresses, connect will be attempted with each of the
|
||||
/// addresses until a connection is successful. If none of the addresses
|
||||
/// result in a successful connection, the error returned from the last
|
||||
/// connection attempt (the last address) is returned.
|
||||
///
|
||||
/// To configure the socket before connecting, you can use the [`TcpSocket`]
|
||||
/// type.
|
||||
///
|
||||
/// [`ToSocketAddrs`]: trait@crate::net::ToSocketAddrs
|
||||
/// [`TcpSocket`]: struct@crate::net::TcpSocket
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
/// use tokio::io::AsyncWriteExt;
|
||||
/// use std::error::Error;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// // Connect to a peer
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// // Write some data.
|
||||
/// stream.write_all(b"hello world!").await?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
|
||||
///
|
||||
/// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
|
||||
/// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
|
||||
pub async fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||
let addrs = to_socket_addrs(addr).await?;
|
||||
cfg_not_wasi! {
|
||||
/// Opens a TCP connection to a remote host.
|
||||
///
|
||||
/// `addr` is an address of the remote host. Anything which implements the
|
||||
/// [`ToSocketAddrs`] trait can be supplied as the address. If `addr`
|
||||
/// yields multiple addresses, connect will be attempted with each of the
|
||||
/// addresses until a connection is successful. If none of the addresses
|
||||
/// result in a successful connection, the error returned from the last
|
||||
/// connection attempt (the last address) is returned.
|
||||
///
|
||||
/// To configure the socket before connecting, you can use the [`TcpSocket`]
|
||||
/// type.
|
||||
///
|
||||
/// [`ToSocketAddrs`]: trait@crate::net::ToSocketAddrs
|
||||
/// [`TcpSocket`]: struct@crate::net::TcpSocket
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
/// use tokio::io::AsyncWriteExt;
|
||||
/// use std::error::Error;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// // Connect to a peer
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// // Write some data.
|
||||
/// stream.write_all(b"hello world!").await?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
|
||||
///
|
||||
/// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
|
||||
/// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
|
||||
pub async fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||
let addrs = to_socket_addrs(addr).await?;
|
||||
|
||||
let mut last_err = None;
|
||||
let mut last_err = None;
|
||||
|
||||
for addr in addrs {
|
||||
match TcpStream::connect_addr(addr).await {
|
||||
Ok(stream) => return Ok(stream),
|
||||
Err(e) => last_err = Some(e),
|
||||
for addr in addrs {
|
||||
match TcpStream::connect_addr(addr).await {
|
||||
Ok(stream) => return Ok(stream),
|
||||
Err(e) => last_err = Some(e),
|
||||
}
|
||||
}
|
||||
|
||||
Err(last_err.unwrap_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"could not resolve to any address",
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
Err(last_err.unwrap_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"could not resolve to any address",
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
/// Establishes a connection to the specified `addr`.
|
||||
async fn connect_addr(addr: SocketAddr) -> io::Result<TcpStream> {
|
||||
let sys = mio::net::TcpStream::connect(addr)?;
|
||||
TcpStream::connect_mio(sys).await
|
||||
}
|
||||
|
||||
pub(crate) async fn connect_mio(sys: mio::net::TcpStream) -> io::Result<TcpStream> {
|
||||
let stream = TcpStream::new(sys)?;
|
||||
|
||||
// Once we've connected, wait for the stream to be writable as
|
||||
// that's when the actual connection has been initiated. Once we're
|
||||
// writable we check for `take_socket_error` to see if the connect
|
||||
// actually hit an error or not.
|
||||
//
|
||||
// If all that succeeded then we ship everything on up.
|
||||
poll_fn(|cx| stream.io.registration().poll_write_ready(cx)).await?;
|
||||
|
||||
if let Some(e) = stream.io.take_error()? {
|
||||
return Err(e);
|
||||
/// Establishes a connection to the specified `addr`.
|
||||
async fn connect_addr(addr: SocketAddr) -> io::Result<TcpStream> {
|
||||
let sys = mio::net::TcpStream::connect(addr)?;
|
||||
TcpStream::connect_mio(sys).await
|
||||
}
|
||||
|
||||
Ok(stream)
|
||||
pub(crate) async fn connect_mio(sys: mio::net::TcpStream) -> io::Result<TcpStream> {
|
||||
let stream = TcpStream::new(sys)?;
|
||||
|
||||
// Once we've connected, wait for the stream to be writable as
|
||||
// that's when the actual connection has been initiated. Once we're
|
||||
// writable we check for `take_socket_error` to see if the connect
|
||||
// actually hit an error or not.
|
||||
//
|
||||
// If all that succeeded then we ship everything on up.
|
||||
poll_fn(|cx| stream.io.registration().poll_write_ready(cx)).await?;
|
||||
|
||||
if let Some(e) = stream.io.take_error()? {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
Ok(stream)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new(connected: mio::net::TcpStream) -> io::Result<TcpStream> {
|
||||
|
@ -181,11 +186,13 @@ impl TcpStream {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if thread-local runtime is not set.
|
||||
/// This function panics if it is not called from within a runtime with
|
||||
/// IO enabled.
|
||||
///
|
||||
/// The runtime is usually set implicitly when this function is called
|
||||
/// from a future driven by a tokio runtime, otherwise runtime can be set
|
||||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
|
||||
#[track_caller]
|
||||
pub fn from_std(stream: std::net::TcpStream) -> io::Result<TcpStream> {
|
||||
let io = mio::net::TcpStream::from_std(stream);
|
||||
let io = PollEvented::new(io)?;
|
||||
|
@ -244,6 +251,15 @@ impl TcpStream {
|
|||
.map(|io| io.into_raw_socket())
|
||||
.map(|raw_socket| unsafe { std::net::TcpStream::from_raw_socket(raw_socket) })
|
||||
}
|
||||
|
||||
#[cfg(tokio_wasi)]
|
||||
{
|
||||
use std::os::wasi::io::{FromRawFd, IntoRawFd};
|
||||
self.io
|
||||
.into_inner()
|
||||
.map(|io| io.into_raw_fd())
|
||||
.map(|raw_fd| unsafe { std::net::TcpStream::from_raw_fd(raw_fd) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the local address that this stream is bound to.
|
||||
|
@ -361,6 +377,12 @@ impl TcpStream {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
/// This method is cancel safe. Once a readiness event occurs, the method
|
||||
|
@ -531,8 +553,12 @@ impl TcpStream {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the stream's read half is closed
|
||||
/// and will no longer yield data. If the stream is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The stream's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the stream is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -944,7 +970,7 @@ impl TcpStream {
|
|||
/// Tries to read or write from the socket using a user-provided IO operation.
|
||||
///
|
||||
/// If the socket is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the socket by manually
|
||||
/// should attempt to perform IO operation on the socket by manually
|
||||
/// calling the appropriate syscall. If the operation fails because the
|
||||
/// socket is not actually ready, then the closure should return a
|
||||
/// `WouldBlock` error and the readiness flag is cleared. The return value
|
||||
|
@ -963,6 +989,11 @@ impl TcpStream {
|
|||
/// defined on the Tokio `TcpStream` type, as this will mess with the
|
||||
/// readiness flag and can cause the socket to behave incorrectly.
|
||||
///
|
||||
/// This method is not intended to be used with combined interests.
|
||||
/// The closure should perform only one type of IO operation, so it should not
|
||||
/// require more than one ready state. This method may panic or sleep forever
|
||||
/// if it is called with a combined interest.
|
||||
///
|
||||
/// Usually, [`readable()`], [`writable()`] or [`ready()`] is used with this function.
|
||||
///
|
||||
/// [`readable()`]: TcpStream::readable()
|
||||
|
@ -1077,52 +1108,54 @@ impl TcpStream {
|
|||
self.io.set_nodelay(nodelay)
|
||||
}
|
||||
|
||||
/// Reads the linger duration for this socket by getting the `SO_LINGER`
|
||||
/// option.
|
||||
///
|
||||
/// For more information about this option, see [`set_linger`].
|
||||
///
|
||||
/// [`set_linger`]: TcpStream::set_linger
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
///
|
||||
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// println!("{:?}", stream.linger()?);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||
socket2::SockRef::from(self).linger()
|
||||
}
|
||||
cfg_not_wasi! {
|
||||
/// Reads the linger duration for this socket by getting the `SO_LINGER`
|
||||
/// option.
|
||||
///
|
||||
/// For more information about this option, see [`set_linger`].
|
||||
///
|
||||
/// [`set_linger`]: TcpStream::set_linger
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
///
|
||||
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// println!("{:?}", stream.linger()?);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||
socket2::SockRef::from(self).linger()
|
||||
}
|
||||
|
||||
/// Sets the linger duration of this socket by setting the SO_LINGER option.
|
||||
///
|
||||
/// This option controls the action taken when a stream has unsent messages and the stream is
|
||||
/// closed. If SO_LINGER is set, the system shall block the process until it can transmit the
|
||||
/// data or until the time expires.
|
||||
///
|
||||
/// If SO_LINGER is not specified, and the stream is closed, the system handles the call in a
|
||||
/// way that allows the process to continue as quickly as possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
///
|
||||
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// stream.set_linger(None)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
|
||||
socket2::SockRef::from(self).set_linger(dur)
|
||||
/// Sets the linger duration of this socket by setting the SO_LINGER option.
|
||||
///
|
||||
/// This option controls the action taken when a stream has unsent messages and the stream is
|
||||
/// closed. If SO_LINGER is set, the system shall block the process until it can transmit the
|
||||
/// data or until the time expires.
|
||||
///
|
||||
/// If SO_LINGER is not specified, and the stream is closed, the system handles the call in a
|
||||
/// way that allows the process to continue as quickly as possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
///
|
||||
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// stream.set_linger(None)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
|
||||
socket2::SockRef::from(self).set_linger(dur)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the value of the `IP_TTL` option for this socket.
|
||||
|
@ -1315,3 +1348,15 @@ mod sys {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(tokio_unstable, tokio_wasi))]
|
||||
mod sys {
|
||||
use super::TcpStream;
|
||||
use std::os::wasi::prelude::*;
|
||||
|
||||
impl AsRawFd for TcpStream {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.io.as_raw_fd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
106
zeroidc/vendor/tokio/src/net/udp.rs
vendored
106
zeroidc/vendor/tokio/src/net/udp.rs
vendored
|
@ -170,6 +170,7 @@ impl UdpSocket {
|
|||
UdpSocket::new(sys)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn new(socket: mio::net::UdpSocket) -> io::Result<UdpSocket> {
|
||||
let io = PollEvented::new(socket)?;
|
||||
Ok(UdpSocket { io })
|
||||
|
@ -210,6 +211,7 @@ impl UdpSocket {
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[track_caller]
|
||||
pub fn from_std(socket: net::UdpSocket) -> io::Result<UdpSocket> {
|
||||
let io = mio::net::UdpSocket::from_std(socket);
|
||||
UdpSocket::new(io)
|
||||
|
@ -257,6 +259,10 @@ impl UdpSocket {
|
|||
}
|
||||
}
|
||||
|
||||
fn as_socket(&self) -> socket2::SockRef<'_> {
|
||||
socket2::SockRef::from(self)
|
||||
}
|
||||
|
||||
/// Returns the local address that this socket is bound to.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -351,7 +357,9 @@ impl UdpSocket {
|
|||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`.
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
|
@ -734,7 +742,7 @@ impl UdpSocket {
|
|||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
/// This method is cancel safe. If `recv_from` is used as the event in a
|
||||
/// This method is cancel safe. If `recv` is used as the event in a
|
||||
/// [`tokio::select!`](crate::select) statement and some other branch
|
||||
/// completes first, it is guaranteed that no messages were received on this
|
||||
/// socket.
|
||||
|
@ -919,7 +927,7 @@ impl UdpSocket {
|
|||
|
||||
// Safety: We trust `UdpSocket::recv` to have filled up `n` bytes in the
|
||||
// buffer.
|
||||
let n = (&*self.io).recv(dst)?;
|
||||
let n = (*self.io).recv(dst)?;
|
||||
|
||||
unsafe {
|
||||
buf.advance_mut(n);
|
||||
|
@ -983,7 +991,7 @@ impl UdpSocket {
|
|||
|
||||
// Safety: We trust `UdpSocket::recv_from` to have filled up `n` bytes in the
|
||||
// buffer.
|
||||
let (n, addr) = (&*self.io).recv_from(dst)?;
|
||||
let (n, addr) = (*self.io).recv_from(dst)?;
|
||||
|
||||
unsafe {
|
||||
buf.advance_mut(n);
|
||||
|
@ -1265,7 +1273,7 @@ impl UdpSocket {
|
|||
/// Tries to read or write from the socket using a user-provided IO operation.
|
||||
///
|
||||
/// If the socket is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the socket by manually
|
||||
/// should attempt to perform IO operation on the socket by manually
|
||||
/// calling the appropriate syscall. If the operation fails because the
|
||||
/// socket is not actually ready, then the closure should return a
|
||||
/// `WouldBlock` error and the readiness flag is cleared. The return value
|
||||
|
@ -1284,6 +1292,11 @@ impl UdpSocket {
|
|||
/// defined on the Tokio `UdpSocket` type, as this will mess with the
|
||||
/// readiness flag and can cause the socket to behave incorrectly.
|
||||
///
|
||||
/// This method is not intended to be used with combined interests.
|
||||
/// The closure should perform only one type of IO operation, so it should not
|
||||
/// require more than one ready state. This method may panic or sleep forever
|
||||
/// if it is called with a combined interest.
|
||||
///
|
||||
/// Usually, [`readable()`], [`writable()`] or [`ready()`] is used with this function.
|
||||
///
|
||||
/// [`readable()`]: UdpSocket::readable()
|
||||
|
@ -1508,6 +1521,89 @@ impl UdpSocket {
|
|||
self.io.set_ttl(ttl)
|
||||
}
|
||||
|
||||
/// Gets the value of the `IP_TOS` option for this socket.
|
||||
///
|
||||
/// For more information about this option, see [`set_tos`].
|
||||
///
|
||||
/// **NOTE:** On Windows, `IP_TOS` is only supported on [Windows 8+ or
|
||||
/// Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options)
|
||||
///
|
||||
/// [`set_tos`]: Self::set_tos
|
||||
// https://docs.rs/socket2/0.4.2/src/socket2/socket.rs.html#1178
|
||||
#[cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
)))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
))))
|
||||
)]
|
||||
pub fn tos(&self) -> io::Result<u32> {
|
||||
self.as_socket().tos()
|
||||
}
|
||||
|
||||
/// Sets the value for the `IP_TOS` option on this socket.
|
||||
///
|
||||
/// This value sets the type-of-service field that is used in every packet
|
||||
/// sent from this socket.
|
||||
///
|
||||
/// **NOTE:** On Windows, `IP_TOS` is only supported on [Windows 8+ or
|
||||
/// Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options)
|
||||
// https://docs.rs/socket2/0.4.2/src/socket2/socket.rs.html#1178
|
||||
#[cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
)))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
))))
|
||||
)]
|
||||
pub fn set_tos(&self, tos: u32) -> io::Result<()> {
|
||||
self.as_socket().set_tos(tos)
|
||||
}
|
||||
|
||||
/// Gets the value for the `SO_BINDTODEVICE` option on this socket
|
||||
///
|
||||
/// This value gets the socket-bound device's interface name.
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",)))
|
||||
)]
|
||||
pub fn device(&self) -> io::Result<Option<Vec<u8>>> {
|
||||
self.as_socket().device()
|
||||
}
|
||||
|
||||
/// Sets the value for the `SO_BINDTODEVICE` option on this socket
|
||||
///
|
||||
/// If a socket is bound to an interface, only packets received from that
|
||||
/// particular interface are processed by the socket. Note that this only
|
||||
/// works for some socket types, particularly `AF_INET` sockets.
|
||||
///
|
||||
/// If `interface` is `None` or an empty string it removes the binding.
|
||||
#[cfg(all(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(all(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))))
|
||||
)]
|
||||
pub fn bind_device(&self, interface: Option<&[u8]>) -> io::Result<()> {
|
||||
self.as_socket().bind_device(interface)
|
||||
}
|
||||
|
||||
/// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
|
||||
///
|
||||
/// This function specifies a new multicast group for this socket to join.
|
||||
|
|
|
@ -104,7 +104,9 @@ impl UnixDatagram {
|
|||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`.
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
|
@ -430,7 +432,8 @@ impl UnixDatagram {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if thread-local runtime is not set.
|
||||
/// This function panics if it is not called from within a runtime with
|
||||
/// IO enabled.
|
||||
///
|
||||
/// The runtime is usually set implicitly when this function is called
|
||||
/// from a future driven by a Tokio runtime, otherwise runtime can be set
|
||||
|
@ -457,6 +460,7 @@ impl UnixDatagram {
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[track_caller]
|
||||
pub fn from_std(datagram: net::UnixDatagram) -> io::Result<UnixDatagram> {
|
||||
let socket = mio::net::UnixDatagram::from_std(datagram);
|
||||
let io = PollEvented::new(socket)?;
|
||||
|
@ -844,7 +848,7 @@ impl UnixDatagram {
|
|||
|
||||
// Safety: We trust `UnixDatagram::recv_from` to have filled up `n` bytes in the
|
||||
// buffer.
|
||||
let (n, addr) = (&*self.io).recv_from(dst)?;
|
||||
let (n, addr) = (*self.io).recv_from(dst)?;
|
||||
|
||||
unsafe {
|
||||
buf.advance_mut(n);
|
||||
|
@ -907,7 +911,7 @@ impl UnixDatagram {
|
|||
|
||||
// Safety: We trust `UnixDatagram::recv` to have filled up `n` bytes in the
|
||||
// buffer.
|
||||
let n = (&*self.io).recv(dst)?;
|
||||
let n = (*self.io).recv(dst)?;
|
||||
|
||||
unsafe {
|
||||
buf.advance_mut(n);
|
||||
|
@ -1212,7 +1216,7 @@ impl UnixDatagram {
|
|||
/// Tries to read or write from the socket using a user-provided IO operation.
|
||||
///
|
||||
/// If the socket is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the socket by manually
|
||||
/// should attempt to perform IO operation on the socket by manually
|
||||
/// calling the appropriate syscall. If the operation fails because the
|
||||
/// socket is not actually ready, then the closure should return a
|
||||
/// `WouldBlock` error and the readiness flag is cleared. The return value
|
||||
|
@ -1231,6 +1235,11 @@ impl UnixDatagram {
|
|||
/// defined on the Tokio `UnixDatagram` type, as this will mess with the
|
||||
/// readiness flag and can cause the socket to behave incorrectly.
|
||||
///
|
||||
/// This method is not intended to be used with combined interests.
|
||||
/// The closure should perform only one type of IO operation, so it should not
|
||||
/// require more than one ready state. This method may panic or sleep forever
|
||||
/// if it is called with a combined interest.
|
||||
///
|
||||
/// Usually, [`readable()`], [`writable()`] or [`ready()`] is used with this function.
|
||||
///
|
||||
/// [`readable()`]: UnixDatagram::readable()
|
||||
|
|
|
@ -54,11 +54,13 @@ impl UnixListener {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if thread-local runtime is not set.
|
||||
/// This function panics if it is not called from within a runtime with
|
||||
/// IO enabled.
|
||||
///
|
||||
/// The runtime is usually set implicitly when this function is called
|
||||
/// from a future driven by a tokio runtime, otherwise runtime can be set
|
||||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
|
||||
#[track_caller]
|
||||
pub fn bind<P>(path: P) -> io::Result<UnixListener>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
|
@ -77,11 +79,13 @@ impl UnixListener {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if thread-local runtime is not set.
|
||||
/// This function panics if it is not called from within a runtime with
|
||||
/// IO enabled.
|
||||
///
|
||||
/// The runtime is usually set implicitly when this function is called
|
||||
/// from a future driven by a tokio runtime, otherwise runtime can be set
|
||||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
|
||||
#[track_caller]
|
||||
pub fn from_std(listener: net::UnixListener) -> io::Result<UnixListener> {
|
||||
let listener = mio::net::UnixListener::from_std(listener);
|
||||
let io = PollEvented::new(listener)?;
|
||||
|
|
13
zeroidc/vendor/tokio/src/net/unix/mod.rs
vendored
13
zeroidc/vendor/tokio/src/net/unix/mod.rs
vendored
|
@ -1,5 +1,4 @@
|
|||
//! Unix domain socket utility types.
|
||||
|
||||
// This module does not currently provide any public API, but it was
|
||||
// unintentionally defined as a public module. Hide it from the documentation
|
||||
// instead of changing it to a private module to avoid breakage.
|
||||
|
@ -22,3 +21,15 @@ pub(crate) use stream::UnixStream;
|
|||
|
||||
mod ucred;
|
||||
pub use ucred::UCred;
|
||||
|
||||
/// A type representing process and process group IDs.
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type uid_t = u32;
|
||||
|
||||
/// A type representing user ID.
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type gid_t = u32;
|
||||
|
||||
/// A type representing group ID.
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type pid_t = i32;
|
||||
|
|
14
zeroidc/vendor/tokio/src/net/unix/split.rs
vendored
14
zeroidc/vendor/tokio/src/net/unix/split.rs
vendored
|
@ -100,8 +100,12 @@ impl ReadHalf<'_> {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the stream's read half is closed
|
||||
/// and will no longer yield data. If the stream is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The stream's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the stream is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
pub fn try_read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.try_read(buf)
|
||||
|
@ -178,6 +182,12 @@ impl WriteHalf<'_> {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
/// This method is cancel safe. Once a readiness event occurs, the method
|
||||
|
|
24
zeroidc/vendor/tokio/src/net/unix/split_owned.rs
vendored
24
zeroidc/vendor/tokio/src/net/unix/split_owned.rs
vendored
|
@ -114,6 +114,12 @@ impl OwnedReadHalf {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
/// This method is cancel safe. Once a readiness event occurs, the method
|
||||
|
@ -155,8 +161,12 @@ impl OwnedReadHalf {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the stream's read half is closed
|
||||
/// and will no longer yield data. If the stream is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The stream's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the stream is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
pub fn try_read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.try_read(buf)
|
||||
|
@ -261,6 +271,12 @@ impl OwnedWriteHalf {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
/// This method is cancel safe. Once a readiness event occurs, the method
|
||||
|
@ -382,12 +398,12 @@ impl AsyncWrite for OwnedWriteHalf {
|
|||
|
||||
impl AsRef<UnixStream> for OwnedReadHalf {
|
||||
fn as_ref(&self) -> &UnixStream {
|
||||
&*self.inner
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<UnixStream> for OwnedWriteHalf {
|
||||
fn as_ref(&self) -> &UnixStream {
|
||||
&*self.inner
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
|
30
zeroidc/vendor/tokio/src/net/unix/stream.rs
vendored
30
zeroidc/vendor/tokio/src/net/unix/stream.rs
vendored
|
@ -22,8 +22,8 @@ cfg_io_util! {
|
|||
cfg_net_unix! {
|
||||
/// A structure representing a connected Unix socket.
|
||||
///
|
||||
/// This socket can be connected directly with `UnixStream::connect` or accepted
|
||||
/// from a listener with `UnixListener::incoming`. Additionally, a pair of
|
||||
/// This socket can be connected directly with [`UnixStream::connect`] or accepted
|
||||
/// from a listener with [`UnixListener::accept`]. Additionally, a pair of
|
||||
/// anonymous Unix sockets can be created with `UnixStream::pair`.
|
||||
///
|
||||
/// To shut down the stream in the write direction, you can call the
|
||||
|
@ -32,6 +32,7 @@ cfg_net_unix! {
|
|||
/// the stream in one direction.
|
||||
///
|
||||
/// [`shutdown()`]: fn@crate::io::AsyncWriteExt::shutdown
|
||||
/// [`UnixListener::accept`]: crate::net::UnixListener::accept
|
||||
pub struct UnixStream {
|
||||
io: PollEvented<mio::net::UnixStream>,
|
||||
}
|
||||
|
@ -65,6 +66,12 @@ impl UnixStream {
|
|||
/// can be used to concurrently read / write to the same socket on a single
|
||||
/// task without splitting the socket.
|
||||
///
|
||||
/// The function may complete without the socket being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Cancel safety
|
||||
///
|
||||
/// This method is cancel safe. Once a readiness event occurs, the method
|
||||
|
@ -239,8 +246,12 @@ impl UnixStream {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the stream's read half is closed
|
||||
/// and will no longer yield data. If the stream is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The stream's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the stream is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -656,7 +667,7 @@ impl UnixStream {
|
|||
/// Tries to read or write from the socket using a user-provided IO operation.
|
||||
///
|
||||
/// If the socket is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the socket by manually
|
||||
/// should attempt to perform IO operation on the socket by manually
|
||||
/// calling the appropriate syscall. If the operation fails because the
|
||||
/// socket is not actually ready, then the closure should return a
|
||||
/// `WouldBlock` error and the readiness flag is cleared. The return value
|
||||
|
@ -675,6 +686,11 @@ impl UnixStream {
|
|||
/// defined on the Tokio `UnixStream` type, as this will mess with the
|
||||
/// readiness flag and can cause the socket to behave incorrectly.
|
||||
///
|
||||
/// This method is not intended to be used with combined interests.
|
||||
/// The closure should perform only one type of IO operation, so it should not
|
||||
/// require more than one ready state. This method may panic or sleep forever
|
||||
/// if it is called with a combined interest.
|
||||
///
|
||||
/// Usually, [`readable()`], [`writable()`] or [`ready()`] is used with this function.
|
||||
///
|
||||
/// [`readable()`]: UnixStream::readable()
|
||||
|
@ -699,11 +715,13 @@ impl UnixStream {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if thread-local runtime is not set.
|
||||
/// This function panics if it is not called from within a runtime with
|
||||
/// IO enabled.
|
||||
///
|
||||
/// The runtime is usually set implicitly when this function is called
|
||||
/// from a future driven by a tokio runtime, otherwise runtime can be set
|
||||
/// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
|
||||
#[track_caller]
|
||||
pub fn from_std(stream: net::UnixStream) -> io::Result<UnixStream> {
|
||||
let stream = mio::net::UnixStream::from_std(stream);
|
||||
let io = PollEvented::new(stream)?;
|
||||
|
|
52
zeroidc/vendor/tokio/src/net/unix/ucred.rs
vendored
52
zeroidc/vendor/tokio/src/net/unix/ucred.rs
vendored
|
@ -1,24 +1,24 @@
|
|||
use libc::{gid_t, pid_t, uid_t};
|
||||
use crate::net::unix;
|
||||
|
||||
/// Credentials of a process.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct UCred {
|
||||
/// PID (process ID) of the process.
|
||||
pid: Option<pid_t>,
|
||||
pid: Option<unix::pid_t>,
|
||||
/// UID (user ID) of the process.
|
||||
uid: uid_t,
|
||||
uid: unix::uid_t,
|
||||
/// GID (group ID) of the process.
|
||||
gid: gid_t,
|
||||
gid: unix::gid_t,
|
||||
}
|
||||
|
||||
impl UCred {
|
||||
/// Gets UID (user ID) of the process.
|
||||
pub fn uid(&self) -> uid_t {
|
||||
pub fn uid(&self) -> unix::uid_t {
|
||||
self.uid
|
||||
}
|
||||
|
||||
/// Gets GID (group ID) of the process.
|
||||
pub fn gid(&self) -> gid_t {
|
||||
pub fn gid(&self) -> unix::gid_t {
|
||||
self.gid
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ impl UCred {
|
|||
///
|
||||
/// This is only implemented under Linux, Android, iOS, macOS, Solaris and
|
||||
/// Illumos. On other platforms this will always return `None`.
|
||||
pub fn pid(&self) -> Option<pid_t> {
|
||||
pub fn pid(&self) -> Option<unix::pid_t> {
|
||||
self.pid
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ pub(crate) use self::impl_solaris::get_peer_cred;
|
|||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
|
||||
pub(crate) mod impl_linux {
|
||||
use crate::net::unix::UnixStream;
|
||||
use crate::net::unix::{self, UnixStream};
|
||||
|
||||
use libc::{c_void, getsockopt, socklen_t, SOL_SOCKET, SO_PEERCRED};
|
||||
use std::{io, mem};
|
||||
|
@ -87,9 +87,9 @@ pub(crate) mod impl_linux {
|
|||
);
|
||||
if ret == 0 && ucred_size as usize == mem::size_of::<ucred>() {
|
||||
Ok(super::UCred {
|
||||
uid: ucred.uid,
|
||||
gid: ucred.gid,
|
||||
pid: Some(ucred.pid),
|
||||
uid: ucred.uid as unix::uid_t,
|
||||
gid: ucred.gid as unix::gid_t,
|
||||
pid: Some(ucred.pid as unix::pid_t),
|
||||
})
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
|
@ -100,7 +100,7 @@ pub(crate) mod impl_linux {
|
|||
|
||||
#[cfg(any(target_os = "netbsd"))]
|
||||
pub(crate) mod impl_netbsd {
|
||||
use crate::net::unix::UnixStream;
|
||||
use crate::net::unix::{self, UnixStream};
|
||||
|
||||
use libc::{c_void, getsockopt, socklen_t, unpcbid, LOCAL_PEEREID, SOL_SOCKET};
|
||||
use std::io;
|
||||
|
@ -129,9 +129,9 @@ pub(crate) mod impl_netbsd {
|
|||
);
|
||||
if ret == 0 && unpcbid_size as usize == size_of::<unpcbid>() {
|
||||
Ok(super::UCred {
|
||||
uid: unpcbid.unp_euid,
|
||||
gid: unpcbid.unp_egid,
|
||||
pid: Some(unpcbid.unp_pid),
|
||||
uid: unpcbid.unp_euid as unix::uid_t,
|
||||
gid: unpcbid.unp_egid as unix::gid_t,
|
||||
pid: Some(unpcbid.unp_pid as unix::pid_t),
|
||||
})
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
|
@ -142,7 +142,7 @@ pub(crate) mod impl_netbsd {
|
|||
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
|
||||
pub(crate) mod impl_bsd {
|
||||
use crate::net::unix::UnixStream;
|
||||
use crate::net::unix::{self, UnixStream};
|
||||
|
||||
use libc::getpeereid;
|
||||
use std::io;
|
||||
|
@ -160,8 +160,8 @@ pub(crate) mod impl_bsd {
|
|||
|
||||
if ret == 0 {
|
||||
Ok(super::UCred {
|
||||
uid: uid.assume_init(),
|
||||
gid: gid.assume_init(),
|
||||
uid: uid.assume_init() as unix::uid_t,
|
||||
gid: gid.assume_init() as unix::gid_t,
|
||||
pid: None,
|
||||
})
|
||||
} else {
|
||||
|
@ -173,7 +173,7 @@ pub(crate) mod impl_bsd {
|
|||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
pub(crate) mod impl_macos {
|
||||
use crate::net::unix::UnixStream;
|
||||
use crate::net::unix::{self, UnixStream};
|
||||
|
||||
use libc::{c_void, getpeereid, getsockopt, pid_t, LOCAL_PEEREPID, SOL_LOCAL};
|
||||
use std::io;
|
||||
|
@ -207,9 +207,9 @@ pub(crate) mod impl_macos {
|
|||
|
||||
if ret == 0 {
|
||||
Ok(super::UCred {
|
||||
uid: uid.assume_init(),
|
||||
gid: gid.assume_init(),
|
||||
pid: Some(pid.assume_init()),
|
||||
uid: uid.assume_init() as unix::uid_t,
|
||||
gid: gid.assume_init() as unix::gid_t,
|
||||
pid: Some(pid.assume_init() as unix::pid_t),
|
||||
})
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
|
@ -220,7 +220,7 @@ pub(crate) mod impl_macos {
|
|||
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||
pub(crate) mod impl_solaris {
|
||||
use crate::net::unix::UnixStream;
|
||||
use crate::net::unix::{self, UnixStream};
|
||||
use std::io;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::ptr;
|
||||
|
@ -240,9 +240,9 @@ pub(crate) mod impl_solaris {
|
|||
libc::ucred_free(cred);
|
||||
|
||||
Ok(super::UCred {
|
||||
uid,
|
||||
gid,
|
||||
pid: Some(pid),
|
||||
uid: uid as unix::uid_t,
|
||||
gid: gid as unix::gid_t,
|
||||
pid: Some(pid as unix::pid_t),
|
||||
})
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
|
|
398
zeroidc/vendor/tokio/src/net/windows/named_pipe.rs
vendored
398
zeroidc/vendor/tokio/src/net/windows/named_pipe.rs
vendored
|
@ -20,21 +20,18 @@ cfg_io_util! {
|
|||
#[cfg(not(docsrs))]
|
||||
mod doc {
|
||||
pub(super) use crate::os::windows::ffi::OsStrExt;
|
||||
pub(super) use crate::winapi::shared::minwindef::{DWORD, FALSE};
|
||||
pub(super) use crate::winapi::um::fileapi;
|
||||
pub(super) use crate::winapi::um::handleapi;
|
||||
pub(super) use crate::winapi::um::namedpipeapi;
|
||||
pub(super) use crate::winapi::um::winbase;
|
||||
pub(super) use crate::winapi::um::winnt;
|
||||
|
||||
pub(super) mod windows_sys {
|
||||
pub(crate) use windows_sys::{
|
||||
Win32::Foundation::*, Win32::Storage::FileSystem::*, Win32::System::Pipes::*,
|
||||
Win32::System::SystemServices::*,
|
||||
};
|
||||
}
|
||||
pub(super) use mio::windows as mio_windows;
|
||||
}
|
||||
|
||||
// NB: none of these shows up in public API, so don't document them.
|
||||
#[cfg(docsrs)]
|
||||
mod doc {
|
||||
pub type DWORD = crate::doc::NotDefinedHere;
|
||||
|
||||
pub(super) mod mio_windows {
|
||||
pub type NamedPipe = crate::doc::NotDefinedHere;
|
||||
}
|
||||
|
@ -101,7 +98,6 @@ use self::doc::*;
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
/// [`ERROR_PIPE_BUSY`]: crate::winapi::shared::winerror::ERROR_PIPE_BUSY
|
||||
/// [Windows named pipe]: https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipes
|
||||
#[derive(Debug)]
|
||||
pub struct NamedPipeServer {
|
||||
|
@ -192,17 +188,15 @@ impl NamedPipeServer {
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub async fn connect(&self) -> io::Result<()> {
|
||||
loop {
|
||||
match self.io.connect() {
|
||||
Ok(()) => break,
|
||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
self.io.registration().readiness(Interest::WRITABLE).await?;
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
match self.io.connect() {
|
||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
self.io
|
||||
.registration()
|
||||
.async_io(Interest::WRITABLE, || self.io.connect())
|
||||
.await
|
||||
}
|
||||
x => x,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Disconnects the server end of a named pipe instance from a client
|
||||
|
@ -211,7 +205,7 @@ impl NamedPipeServer {
|
|||
/// ```
|
||||
/// use tokio::io::AsyncWriteExt;
|
||||
/// use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
|
||||
/// use winapi::shared::winerror;
|
||||
/// use windows_sys::Win32::Foundation::ERROR_PIPE_NOT_CONNECTED;
|
||||
///
|
||||
/// const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-disconnect";
|
||||
///
|
||||
|
@ -231,7 +225,7 @@ impl NamedPipeServer {
|
|||
/// // Write fails with an OS-specific error after client has been
|
||||
/// // disconnected.
|
||||
/// let e = client.write(b"ping").await.unwrap_err();
|
||||
/// assert_eq!(e.raw_os_error(), Some(winerror::ERROR_PIPE_NOT_CONNECTED as i32));
|
||||
/// assert_eq!(e.raw_os_error(), Some(ERROR_PIPE_NOT_CONNECTED as i32));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn disconnect(&self) -> io::Result<()> {
|
||||
|
@ -244,6 +238,12 @@ impl NamedPipeServer {
|
|||
/// can be used to concurrently read / write to the same pipe on a single
|
||||
/// task without splitting the pipe.
|
||||
///
|
||||
/// The function may complete without the pipe being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Concurrently read and write to the pipe on the same task without
|
||||
|
@ -403,8 +403,12 @@ impl NamedPipeServer {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the pipe's read half is closed
|
||||
/// and will no longer yield data. If the pipe is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The pipe's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the pipe is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -536,7 +540,7 @@ impl NamedPipeServer {
|
|||
/// Tries to read data from the stream into the provided buffer, advancing the
|
||||
/// buffer's internal cursor, returning how many bytes were read.
|
||||
///
|
||||
/// Receives any pending data from the socket but does not wait for new data
|
||||
/// Receives any pending data from the pipe but does not wait for new data
|
||||
/// to arrive. On success, returns the number of bytes read. Because
|
||||
/// `try_read_buf()` is non-blocking, the buffer does not have to be stored by
|
||||
/// the async task and can exist entirely on the stack.
|
||||
|
@ -567,7 +571,7 @@ impl NamedPipeServer {
|
|||
/// let server = named_pipe::ServerOptions::new().create(PIPE_NAME)?;
|
||||
///
|
||||
/// loop {
|
||||
/// // Wait for the socket to be readable
|
||||
/// // Wait for the pipe to be readable
|
||||
/// server.readable().await?;
|
||||
///
|
||||
/// let mut buf = Vec::with_capacity(4096);
|
||||
|
@ -808,27 +812,32 @@ impl NamedPipeServer {
|
|||
.try_io(Interest::WRITABLE, || (&*self.io).write_vectored(buf))
|
||||
}
|
||||
|
||||
/// Tries to read or write from the socket using a user-provided IO operation.
|
||||
/// Tries to read or write from the pipe using a user-provided IO operation.
|
||||
///
|
||||
/// If the socket is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the socket by manually
|
||||
/// If the pipe is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the pipe by manually
|
||||
/// calling the appropriate syscall. If the operation fails because the
|
||||
/// socket is not actually ready, then the closure should return a
|
||||
/// pipe is not actually ready, then the closure should return a
|
||||
/// `WouldBlock` error and the readiness flag is cleared. The return value
|
||||
/// of the closure is then returned by `try_io`.
|
||||
///
|
||||
/// If the socket is not ready, then the closure is not called
|
||||
/// If the pipe is not ready, then the closure is not called
|
||||
/// and a `WouldBlock` error is returned.
|
||||
///
|
||||
/// The closure should only return a `WouldBlock` error if it has performed
|
||||
/// an IO operation on the socket that failed due to the socket not being
|
||||
/// an IO operation on the pipe that failed due to the pipe not being
|
||||
/// ready. Returning a `WouldBlock` error in any other situation will
|
||||
/// incorrectly clear the readiness flag, which can cause the socket to
|
||||
/// incorrectly clear the readiness flag, which can cause the pipe to
|
||||
/// behave incorrectly.
|
||||
///
|
||||
/// The closure should not perform the IO operation using any of the
|
||||
/// methods defined on the Tokio `NamedPipeServer` type, as this will mess with
|
||||
/// the readiness flag and can cause the socket to behave incorrectly.
|
||||
/// the readiness flag and can cause the pipe to behave incorrectly.
|
||||
///
|
||||
/// This method is not intended to be used with combined interests.
|
||||
/// The closure should perform only one type of IO operation, so it should not
|
||||
/// require more than one ready state. This method may panic or sleep forever
|
||||
/// if it is called with a combined interest.
|
||||
///
|
||||
/// Usually, [`readable()`], [`writable()`] or [`ready()`] is used with this function.
|
||||
///
|
||||
|
@ -903,7 +912,7 @@ impl AsRawHandle for NamedPipeServer {
|
|||
/// use std::time::Duration;
|
||||
/// use tokio::net::windows::named_pipe::ClientOptions;
|
||||
/// use tokio::time;
|
||||
/// use winapi::shared::winerror;
|
||||
/// use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
|
||||
///
|
||||
/// const PIPE_NAME: &str = r"\\.\pipe\named-pipe-idiomatic-client";
|
||||
///
|
||||
|
@ -911,7 +920,7 @@ impl AsRawHandle for NamedPipeServer {
|
|||
/// let client = loop {
|
||||
/// match ClientOptions::new().open(PIPE_NAME) {
|
||||
/// Ok(client) => break client,
|
||||
/// Err(e) if e.raw_os_error() == Some(winerror::ERROR_PIPE_BUSY as i32) => (),
|
||||
/// Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY as i32) => (),
|
||||
/// Err(e) => return Err(e),
|
||||
/// }
|
||||
///
|
||||
|
@ -922,7 +931,7 @@ impl AsRawHandle for NamedPipeServer {
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
/// [`ERROR_PIPE_BUSY`]: crate::winapi::shared::winerror::ERROR_PIPE_BUSY
|
||||
/// [`ERROR_PIPE_BUSY`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/Foundation/constant.ERROR_PIPE_BUSY.html
|
||||
/// [Windows named pipe]: https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipes
|
||||
#[derive(Debug)]
|
||||
pub struct NamedPipeClient {
|
||||
|
@ -986,6 +995,12 @@ impl NamedPipeClient {
|
|||
/// can be used to concurrently read / write to the same pipe on a single
|
||||
/// task without splitting the pipe.
|
||||
///
|
||||
/// The function may complete without the pipe being ready. This is a
|
||||
/// false-positive and attempting an operation will return with
|
||||
/// `io::ErrorKind::WouldBlock`. The function can also return with an empty
|
||||
/// [`Ready`] set, so you should always check the returned value and possibly
|
||||
/// wait again if the requested states are not set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Concurrently read and write to the pipe on the same task without
|
||||
|
@ -1143,8 +1158,12 @@ impl NamedPipeClient {
|
|||
/// # Return
|
||||
///
|
||||
/// If data is successfully read, `Ok(n)` is returned, where `n` is the
|
||||
/// number of bytes read. `Ok(0)` indicates the pipe's read half is closed
|
||||
/// and will no longer yield data. If the pipe is not ready to read data
|
||||
/// number of bytes read. If `n` is `0`, then it can indicate one of two scenarios:
|
||||
///
|
||||
/// 1. The pipe's read half is closed and will no longer yield data.
|
||||
/// 2. The specified buffer was 0 bytes in length.
|
||||
///
|
||||
/// If the pipe is not ready to read data,
|
||||
/// `Err(io::ErrorKind::WouldBlock)` is returned.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -1274,7 +1293,7 @@ impl NamedPipeClient {
|
|||
/// Tries to read data from the stream into the provided buffer, advancing the
|
||||
/// buffer's internal cursor, returning how many bytes were read.
|
||||
///
|
||||
/// Receives any pending data from the socket but does not wait for new data
|
||||
/// Receives any pending data from the pipe but does not wait for new data
|
||||
/// to arrive. On success, returns the number of bytes read. Because
|
||||
/// `try_read_buf()` is non-blocking, the buffer does not have to be stored by
|
||||
/// the async task and can exist entirely on the stack.
|
||||
|
@ -1305,7 +1324,7 @@ impl NamedPipeClient {
|
|||
/// let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
|
||||
///
|
||||
/// loop {
|
||||
/// // Wait for the socket to be readable
|
||||
/// // Wait for the pipe to be readable
|
||||
/// client.readable().await?;
|
||||
///
|
||||
/// let mut buf = Vec::with_capacity(4096);
|
||||
|
@ -1543,27 +1562,32 @@ impl NamedPipeClient {
|
|||
.try_io(Interest::WRITABLE, || (&*self.io).write_vectored(buf))
|
||||
}
|
||||
|
||||
/// Tries to read or write from the socket using a user-provided IO operation.
|
||||
/// Tries to read or write from the pipe using a user-provided IO operation.
|
||||
///
|
||||
/// If the socket is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the socket by manually
|
||||
/// If the pipe is ready, the provided closure is called. The closure
|
||||
/// should attempt to perform IO operation from the pipe by manually
|
||||
/// calling the appropriate syscall. If the operation fails because the
|
||||
/// socket is not actually ready, then the closure should return a
|
||||
/// pipe is not actually ready, then the closure should return a
|
||||
/// `WouldBlock` error and the readiness flag is cleared. The return value
|
||||
/// of the closure is then returned by `try_io`.
|
||||
///
|
||||
/// If the socket is not ready, then the closure is not called
|
||||
/// If the pipe is not ready, then the closure is not called
|
||||
/// and a `WouldBlock` error is returned.
|
||||
///
|
||||
/// The closure should only return a `WouldBlock` error if it has performed
|
||||
/// an IO operation on the socket that failed due to the socket not being
|
||||
/// an IO operation on the pipe that failed due to the pipe not being
|
||||
/// ready. Returning a `WouldBlock` error in any other situation will
|
||||
/// incorrectly clear the readiness flag, which can cause the socket to
|
||||
/// incorrectly clear the readiness flag, which can cause the pipe to
|
||||
/// behave incorrectly.
|
||||
///
|
||||
/// The closure should not perform the IO operation using any of the methods
|
||||
/// defined on the Tokio `NamedPipeClient` type, as this will mess with the
|
||||
/// readiness flag and can cause the socket to behave incorrectly.
|
||||
/// readiness flag and can cause the pipe to behave incorrectly.
|
||||
///
|
||||
/// This method is not intended to be used with combined interests.
|
||||
/// The closure should perform only one type of IO operation, so it should not
|
||||
/// require more than one ready state. This method may panic or sleep forever
|
||||
/// if it is called with a combined interest.
|
||||
///
|
||||
/// Usually, [`readable()`], [`writable()`] or [`ready()`] is used with this function.
|
||||
///
|
||||
|
@ -1641,12 +1665,12 @@ macro_rules! bool_flag {
|
|||
/// See [`ServerOptions::create`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ServerOptions {
|
||||
open_mode: DWORD,
|
||||
pipe_mode: DWORD,
|
||||
max_instances: DWORD,
|
||||
out_buffer_size: DWORD,
|
||||
in_buffer_size: DWORD,
|
||||
default_timeout: DWORD,
|
||||
open_mode: u32,
|
||||
pipe_mode: u32,
|
||||
max_instances: u32,
|
||||
out_buffer_size: u32,
|
||||
in_buffer_size: u32,
|
||||
default_timeout: u32,
|
||||
}
|
||||
|
||||
impl ServerOptions {
|
||||
|
@ -1663,9 +1687,9 @@ impl ServerOptions {
|
|||
/// ```
|
||||
pub fn new() -> ServerOptions {
|
||||
ServerOptions {
|
||||
open_mode: winbase::PIPE_ACCESS_DUPLEX | winbase::FILE_FLAG_OVERLAPPED,
|
||||
pipe_mode: winbase::PIPE_TYPE_BYTE | winbase::PIPE_REJECT_REMOTE_CLIENTS,
|
||||
max_instances: winbase::PIPE_UNLIMITED_INSTANCES,
|
||||
open_mode: windows_sys::PIPE_ACCESS_DUPLEX | windows_sys::FILE_FLAG_OVERLAPPED,
|
||||
pipe_mode: windows_sys::PIPE_TYPE_BYTE | windows_sys::PIPE_REJECT_REMOTE_CLIENTS,
|
||||
max_instances: windows_sys::PIPE_UNLIMITED_INSTANCES,
|
||||
out_buffer_size: 65536,
|
||||
in_buffer_size: 65536,
|
||||
default_timeout: 0,
|
||||
|
@ -1681,11 +1705,10 @@ impl ServerOptions {
|
|||
///
|
||||
/// [`dwPipeMode`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
|
||||
pub fn pipe_mode(&mut self, pipe_mode: PipeMode) -> &mut Self {
|
||||
self.pipe_mode = match pipe_mode {
|
||||
PipeMode::Byte => winbase::PIPE_TYPE_BYTE,
|
||||
PipeMode::Message => winbase::PIPE_TYPE_MESSAGE,
|
||||
};
|
||||
|
||||
let is_msg = matches!(pipe_mode, PipeMode::Message);
|
||||
// Pipe mode is implemented as a bit flag 0x4. Set is message and unset
|
||||
// is byte.
|
||||
bool_flag!(self.pipe_mode, is_msg, windows_sys::PIPE_TYPE_MESSAGE);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1781,7 +1804,7 @@ impl ServerOptions {
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn access_inbound(&mut self, allowed: bool) -> &mut Self {
|
||||
bool_flag!(self.open_mode, allowed, winbase::PIPE_ACCESS_INBOUND);
|
||||
bool_flag!(self.open_mode, allowed, windows_sys::PIPE_ACCESS_INBOUND);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1879,7 +1902,7 @@ impl ServerOptions {
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn access_outbound(&mut self, allowed: bool) -> &mut Self {
|
||||
bool_flag!(self.open_mode, allowed, winbase::PIPE_ACCESS_OUTBOUND);
|
||||
bool_flag!(self.open_mode, allowed, windows_sys::PIPE_ACCESS_OUTBOUND);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1950,7 +1973,113 @@ impl ServerOptions {
|
|||
bool_flag!(
|
||||
self.open_mode,
|
||||
first,
|
||||
winbase::FILE_FLAG_FIRST_PIPE_INSTANCE
|
||||
windows_sys::FILE_FLAG_FIRST_PIPE_INSTANCE
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
/// Requests permission to modify the pipe's discretionary access control list.
|
||||
///
|
||||
/// This corresponds to setting [`WRITE_DAC`] in dwOpenMode.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::{io, os::windows::prelude::AsRawHandle, ptr};
|
||||
//
|
||||
/// use tokio::net::windows::named_pipe::ServerOptions;
|
||||
/// use windows_sys::{
|
||||
/// Win32::Foundation::ERROR_SUCCESS,
|
||||
/// Win32::Security::DACL_SECURITY_INFORMATION,
|
||||
/// Win32::Security::Authorization::{SetSecurityInfo, SE_KERNEL_OBJECT},
|
||||
/// };
|
||||
///
|
||||
/// const PIPE_NAME: &str = r"\\.\pipe\write_dac_pipe";
|
||||
///
|
||||
/// # #[tokio::main] async fn main() -> io::Result<()> {
|
||||
/// let mut pipe_template = ServerOptions::new();
|
||||
/// pipe_template.write_dac(true);
|
||||
/// let pipe = pipe_template.create(PIPE_NAME)?;
|
||||
///
|
||||
/// unsafe {
|
||||
/// assert_eq!(
|
||||
/// ERROR_SUCCESS,
|
||||
/// SetSecurityInfo(
|
||||
/// pipe.as_raw_handle() as _,
|
||||
/// SE_KERNEL_OBJECT,
|
||||
/// DACL_SECURITY_INFORMATION,
|
||||
/// ptr::null_mut(),
|
||||
/// ptr::null_mut(),
|
||||
/// ptr::null_mut(),
|
||||
/// ptr::null_mut(),
|
||||
/// )
|
||||
/// );
|
||||
/// }
|
||||
///
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use std::{io, os::windows::prelude::AsRawHandle, ptr};
|
||||
//
|
||||
/// use tokio::net::windows::named_pipe::ServerOptions;
|
||||
/// use windows_sys::{
|
||||
/// Win32::Foundation::ERROR_ACCESS_DENIED,
|
||||
/// Win32::Security::DACL_SECURITY_INFORMATION,
|
||||
/// Win32::Security::Authorization::{SetSecurityInfo, SE_KERNEL_OBJECT},
|
||||
/// };
|
||||
///
|
||||
/// const PIPE_NAME: &str = r"\\.\pipe\write_dac_pipe_fail";
|
||||
///
|
||||
/// # #[tokio::main] async fn main() -> io::Result<()> {
|
||||
/// let mut pipe_template = ServerOptions::new();
|
||||
/// pipe_template.write_dac(false);
|
||||
/// let pipe = pipe_template.create(PIPE_NAME)?;
|
||||
///
|
||||
/// unsafe {
|
||||
/// assert_eq!(
|
||||
/// ERROR_ACCESS_DENIED,
|
||||
/// SetSecurityInfo(
|
||||
/// pipe.as_raw_handle() as _,
|
||||
/// SE_KERNEL_OBJECT,
|
||||
/// DACL_SECURITY_INFORMATION,
|
||||
/// ptr::null_mut(),
|
||||
/// ptr::null_mut(),
|
||||
/// ptr::null_mut(),
|
||||
/// ptr::null_mut(),
|
||||
/// )
|
||||
/// );
|
||||
/// }
|
||||
///
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
/// [`WRITE_DAC`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
|
||||
pub fn write_dac(&mut self, requested: bool) -> &mut Self {
|
||||
bool_flag!(self.open_mode, requested, windows_sys::WRITE_DAC);
|
||||
self
|
||||
}
|
||||
|
||||
/// Requests permission to modify the pipe's owner.
|
||||
///
|
||||
/// This corresponds to setting [`WRITE_OWNER`] in dwOpenMode.
|
||||
///
|
||||
/// [`WRITE_OWNER`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
|
||||
pub fn write_owner(&mut self, requested: bool) -> &mut Self {
|
||||
bool_flag!(self.open_mode, requested, windows_sys::WRITE_OWNER);
|
||||
self
|
||||
}
|
||||
|
||||
/// Requests permission to modify the pipe's system access control list.
|
||||
///
|
||||
/// This corresponds to setting [`ACCESS_SYSTEM_SECURITY`] in dwOpenMode.
|
||||
///
|
||||
/// [`ACCESS_SYSTEM_SECURITY`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
|
||||
pub fn access_system_security(&mut self, requested: bool) -> &mut Self {
|
||||
bool_flag!(
|
||||
self.open_mode,
|
||||
requested,
|
||||
windows_sys::ACCESS_SYSTEM_SECURITY
|
||||
);
|
||||
self
|
||||
}
|
||||
|
@ -1962,7 +2091,11 @@ impl ServerOptions {
|
|||
///
|
||||
/// [`PIPE_REJECT_REMOTE_CLIENTS`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea#pipe_reject_remote_clients
|
||||
pub fn reject_remote_clients(&mut self, reject: bool) -> &mut Self {
|
||||
bool_flag!(self.pipe_mode, reject, winbase::PIPE_REJECT_REMOTE_CLIENTS);
|
||||
bool_flag!(
|
||||
self.pipe_mode,
|
||||
reject,
|
||||
windows_sys::PIPE_REJECT_REMOTE_CLIENTS
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1984,7 +2117,7 @@ impl ServerOptions {
|
|||
/// ```
|
||||
/// use std::io;
|
||||
/// use tokio::net::windows::named_pipe::{ServerOptions, ClientOptions};
|
||||
/// use winapi::shared::winerror;
|
||||
/// use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
|
||||
///
|
||||
/// const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-max-instances";
|
||||
///
|
||||
|
@ -2000,11 +2133,11 @@ impl ServerOptions {
|
|||
///
|
||||
/// // Too many servers!
|
||||
/// let e = server.create(PIPE_NAME).unwrap_err();
|
||||
/// assert_eq!(e.raw_os_error(), Some(winerror::ERROR_PIPE_BUSY as i32));
|
||||
/// assert_eq!(e.raw_os_error(), Some(ERROR_PIPE_BUSY as i32));
|
||||
///
|
||||
/// // Still too many servers even if we specify a higher value!
|
||||
/// let e = server.max_instances(100).create(PIPE_NAME).unwrap_err();
|
||||
/// assert_eq!(e.raw_os_error(), Some(winerror::ERROR_PIPE_BUSY as i32));
|
||||
/// assert_eq!(e.raw_os_error(), Some(ERROR_PIPE_BUSY as i32));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
|
@ -2020,9 +2153,10 @@ impl ServerOptions {
|
|||
/// let builder = ServerOptions::new().max_instances(255);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[track_caller]
|
||||
pub fn max_instances(&mut self, instances: usize) -> &mut Self {
|
||||
assert!(instances < 255, "cannot specify more than 254 instances");
|
||||
self.max_instances = instances as DWORD;
|
||||
self.max_instances = instances as u32;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -2032,7 +2166,7 @@ impl ServerOptions {
|
|||
///
|
||||
/// [`nOutBufferSize`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
|
||||
pub fn out_buffer_size(&mut self, buffer: u32) -> &mut Self {
|
||||
self.out_buffer_size = buffer as DWORD;
|
||||
self.out_buffer_size = buffer;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -2042,7 +2176,7 @@ impl ServerOptions {
|
|||
///
|
||||
/// [`nInBufferSize`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
|
||||
pub fn in_buffer_size(&mut self, buffer: u32) -> &mut Self {
|
||||
self.in_buffer_size = buffer as DWORD;
|
||||
self.in_buffer_size = buffer;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -2099,7 +2233,7 @@ impl ServerOptions {
|
|||
///
|
||||
/// [`create`]: ServerOptions::create
|
||||
/// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
/// [`SECURITY_ATTRIBUTES`]: crate::winapi::um::minwinbase::SECURITY_ATTRIBUTES
|
||||
/// [`SECURITY_ATTRIBUTES`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/Security/struct.SECURITY_ATTRIBUTES.html
|
||||
pub unsafe fn create_with_security_attributes_raw(
|
||||
&self,
|
||||
addr: impl AsRef<OsStr>,
|
||||
|
@ -2107,7 +2241,7 @@ impl ServerOptions {
|
|||
) -> io::Result<NamedPipeServer> {
|
||||
let addr = encode_addr(addr);
|
||||
|
||||
let h = namedpipeapi::CreateNamedPipeW(
|
||||
let h = windows_sys::CreateNamedPipeW(
|
||||
addr.as_ptr(),
|
||||
self.open_mode,
|
||||
self.pipe_mode,
|
||||
|
@ -2118,11 +2252,11 @@ impl ServerOptions {
|
|||
attrs as *mut _,
|
||||
);
|
||||
|
||||
if h == handleapi::INVALID_HANDLE_VALUE {
|
||||
if h == windows_sys::INVALID_HANDLE_VALUE {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
NamedPipeServer::from_raw_handle(h)
|
||||
NamedPipeServer::from_raw_handle(h as _)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2132,8 +2266,8 @@ impl ServerOptions {
|
|||
/// See [`ClientOptions::open`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClientOptions {
|
||||
desired_access: DWORD,
|
||||
security_qos_flags: DWORD,
|
||||
desired_access: u32,
|
||||
security_qos_flags: u32,
|
||||
}
|
||||
|
||||
impl ClientOptions {
|
||||
|
@ -2152,8 +2286,9 @@ impl ClientOptions {
|
|||
/// ```
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
desired_access: winnt::GENERIC_READ | winnt::GENERIC_WRITE,
|
||||
security_qos_flags: winbase::SECURITY_IDENTIFICATION | winbase::SECURITY_SQOS_PRESENT,
|
||||
desired_access: windows_sys::GENERIC_READ | windows_sys::GENERIC_WRITE,
|
||||
security_qos_flags: windows_sys::SECURITY_IDENTIFICATION
|
||||
| windows_sys::SECURITY_SQOS_PRESENT,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2164,7 +2299,7 @@ impl ClientOptions {
|
|||
/// [`GENERIC_READ`]: https://docs.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
|
||||
/// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
pub fn read(&mut self, allowed: bool) -> &mut Self {
|
||||
bool_flag!(self.desired_access, allowed, winnt::GENERIC_READ);
|
||||
bool_flag!(self.desired_access, allowed, windows_sys::GENERIC_READ);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -2175,7 +2310,7 @@ impl ClientOptions {
|
|||
/// [`GENERIC_WRITE`]: https://docs.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
|
||||
/// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
pub fn write(&mut self, allowed: bool) -> &mut Self {
|
||||
bool_flag!(self.desired_access, allowed, winnt::GENERIC_WRITE);
|
||||
bool_flag!(self.desired_access, allowed, windows_sys::GENERIC_WRITE);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -2198,11 +2333,11 @@ impl ClientOptions {
|
|||
/// automatically when using this method.
|
||||
///
|
||||
/// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
|
||||
/// [`SECURITY_IDENTIFICATION`]: crate::winapi::um::winbase::SECURITY_IDENTIFICATION
|
||||
/// [`SECURITY_IDENTIFICATION`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/Storage/FileSystem/constant.SECURITY_IDENTIFICATION.html
|
||||
/// [Impersonation Levels]: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level
|
||||
pub fn security_qos_flags(&mut self, flags: u32) -> &mut Self {
|
||||
// See: https://github.com/rust-lang/rust/pull/58216
|
||||
self.security_qos_flags = flags | winbase::SECURITY_SQOS_PRESENT;
|
||||
self.security_qos_flags = flags | windows_sys::SECURITY_SQOS_PRESENT;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -2227,8 +2362,7 @@ impl ClientOptions {
|
|||
/// but the server is not currently waiting for a connection. Please see the
|
||||
/// examples for how to check for this error.
|
||||
///
|
||||
/// [`ERROR_PIPE_BUSY`]: crate::winapi::shared::winerror::ERROR_PIPE_BUSY
|
||||
/// [`winapi`]: crate::winapi
|
||||
/// [`ERROR_PIPE_BUSY`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/Foundation/constant.ERROR_PIPE_BUSY.html
|
||||
/// [enabled I/O]: crate::runtime::Builder::enable_io
|
||||
/// [Tokio Runtime]: crate::runtime::Runtime
|
||||
///
|
||||
|
@ -2239,7 +2373,7 @@ impl ClientOptions {
|
|||
/// use std::time::Duration;
|
||||
/// use tokio::net::windows::named_pipe::ClientOptions;
|
||||
/// use tokio::time;
|
||||
/// use winapi::shared::winerror;
|
||||
/// use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
|
||||
///
|
||||
/// const PIPE_NAME: &str = r"\\.\pipe\mynamedpipe";
|
||||
///
|
||||
|
@ -2247,7 +2381,7 @@ impl ClientOptions {
|
|||
/// let client = loop {
|
||||
/// match ClientOptions::new().open(PIPE_NAME) {
|
||||
/// Ok(client) => break client,
|
||||
/// Err(e) if e.raw_os_error() == Some(winerror::ERROR_PIPE_BUSY as i32) => (),
|
||||
/// Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY as i32) => (),
|
||||
/// Err(e) => return Err(e),
|
||||
/// }
|
||||
///
|
||||
|
@ -2277,7 +2411,7 @@ impl ClientOptions {
|
|||
///
|
||||
/// [`open`]: ClientOptions::open
|
||||
/// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
/// [`SECURITY_ATTRIBUTES`]: crate::winapi::um::minwinbase::SECURITY_ATTRIBUTES
|
||||
/// [`SECURITY_ATTRIBUTES`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/Security/struct.SECURITY_ATTRIBUTES.html
|
||||
pub unsafe fn open_with_security_attributes_raw(
|
||||
&self,
|
||||
addr: impl AsRef<OsStr>,
|
||||
|
@ -2286,28 +2420,28 @@ impl ClientOptions {
|
|||
let addr = encode_addr(addr);
|
||||
|
||||
// NB: We could use a platform specialized `OpenOptions` here, but since
|
||||
// we have access to winapi it ultimately doesn't hurt to use
|
||||
// we have access to windows_sys it ultimately doesn't hurt to use
|
||||
// `CreateFile` explicitly since it allows the use of our already
|
||||
// well-structured wide `addr` to pass into CreateFileW.
|
||||
let h = fileapi::CreateFileW(
|
||||
let h = windows_sys::CreateFileW(
|
||||
addr.as_ptr(),
|
||||
self.desired_access,
|
||||
0,
|
||||
attrs as *mut _,
|
||||
fileapi::OPEN_EXISTING,
|
||||
windows_sys::OPEN_EXISTING,
|
||||
self.get_flags(),
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
);
|
||||
|
||||
if h == handleapi::INVALID_HANDLE_VALUE {
|
||||
if h == windows_sys::INVALID_HANDLE_VALUE {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
NamedPipeClient::from_raw_handle(h)
|
||||
NamedPipeClient::from_raw_handle(h as _)
|
||||
}
|
||||
|
||||
fn get_flags(&self) -> u32 {
|
||||
self.security_qos_flags | winbase::FILE_FLAG_OVERLAPPED
|
||||
self.security_qos_flags | windows_sys::FILE_FLAG_OVERLAPPED
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2320,16 +2454,19 @@ pub enum PipeMode {
|
|||
/// Data is written to the pipe as a stream of bytes. The pipe does not
|
||||
/// distinguish bytes written during different write operations.
|
||||
///
|
||||
/// Corresponds to [`PIPE_TYPE_BYTE`][crate::winapi::um::winbase::PIPE_TYPE_BYTE].
|
||||
/// Corresponds to [`PIPE_TYPE_BYTE`].
|
||||
///
|
||||
/// [`PIPE_TYPE_BYTE`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Pipes/constant.PIPE_TYPE_BYTE.html
|
||||
Byte,
|
||||
/// Data is written to the pipe as a stream of messages. The pipe treats the
|
||||
/// bytes written during each write operation as a message unit. Any reading
|
||||
/// on a named pipe returns [`ERROR_MORE_DATA`] when a message is not read
|
||||
/// completely.
|
||||
///
|
||||
/// Corresponds to [`PIPE_TYPE_MESSAGE`][crate::winapi::um::winbase::PIPE_TYPE_MESSAGE].
|
||||
/// Corresponds to [`PIPE_TYPE_MESSAGE`].
|
||||
///
|
||||
/// [`ERROR_MORE_DATA`]: crate::winapi::shared::winerror::ERROR_MORE_DATA
|
||||
/// [`ERROR_MORE_DATA`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/Foundation/constant.ERROR_MORE_DATA.html
|
||||
/// [`PIPE_TYPE_MESSAGE`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Pipes/constant.PIPE_TYPE_MESSAGE.html
|
||||
Message,
|
||||
}
|
||||
|
||||
|
@ -2339,11 +2476,15 @@ pub enum PipeMode {
|
|||
pub enum PipeEnd {
|
||||
/// The named pipe refers to the client end of a named pipe instance.
|
||||
///
|
||||
/// Corresponds to [`PIPE_CLIENT_END`][crate::winapi::um::winbase::PIPE_CLIENT_END].
|
||||
/// Corresponds to [`PIPE_CLIENT_END`].
|
||||
///
|
||||
/// [`PIPE_CLIENT_END`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Pipes/constant.PIPE_CLIENT_END.html
|
||||
Client,
|
||||
/// The named pipe refers to the server end of a named pipe instance.
|
||||
///
|
||||
/// Corresponds to [`PIPE_SERVER_END`][crate::winapi::um::winbase::PIPE_SERVER_END].
|
||||
/// Corresponds to [`PIPE_SERVER_END`].
|
||||
///
|
||||
/// [`PIPE_SERVER_END`]: https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Pipes/constant.PIPE_SERVER_END.html
|
||||
Server,
|
||||
}
|
||||
|
||||
|
@ -2381,26 +2522,26 @@ unsafe fn named_pipe_info(handle: RawHandle) -> io::Result<PipeInfo> {
|
|||
let mut in_buffer_size = 0;
|
||||
let mut max_instances = 0;
|
||||
|
||||
let result = namedpipeapi::GetNamedPipeInfo(
|
||||
handle,
|
||||
let result = windows_sys::GetNamedPipeInfo(
|
||||
handle as _,
|
||||
&mut flags,
|
||||
&mut out_buffer_size,
|
||||
&mut in_buffer_size,
|
||||
&mut max_instances,
|
||||
);
|
||||
|
||||
if result == FALSE {
|
||||
if result == 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let mut end = PipeEnd::Client;
|
||||
let mut mode = PipeMode::Byte;
|
||||
|
||||
if flags & winbase::PIPE_SERVER_END != 0 {
|
||||
if flags & windows_sys::PIPE_SERVER_END != 0 {
|
||||
end = PipeEnd::Server;
|
||||
}
|
||||
|
||||
if flags & winbase::PIPE_TYPE_MESSAGE != 0 {
|
||||
if flags & windows_sys::PIPE_TYPE_MESSAGE != 0 {
|
||||
mode = PipeMode::Message;
|
||||
}
|
||||
|
||||
|
@ -2412,3 +2553,48 @@ unsafe fn named_pipe_info(handle: RawHandle) -> io::Result<PipeInfo> {
|
|||
max_instances,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use self::windows_sys::{PIPE_REJECT_REMOTE_CLIENTS, PIPE_TYPE_BYTE, PIPE_TYPE_MESSAGE};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn opts_default_pipe_mode() {
|
||||
let opts = ServerOptions::new();
|
||||
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opts_unset_reject_remote() {
|
||||
let mut opts = ServerOptions::new();
|
||||
opts.reject_remote_clients(false);
|
||||
assert_eq!(opts.pipe_mode & PIPE_REJECT_REMOTE_CLIENTS, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opts_set_pipe_mode_maintains_reject_remote_clients() {
|
||||
let mut opts = ServerOptions::new();
|
||||
opts.pipe_mode(PipeMode::Byte);
|
||||
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS);
|
||||
|
||||
opts.reject_remote_clients(false);
|
||||
opts.pipe_mode(PipeMode::Byte);
|
||||
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE);
|
||||
|
||||
opts.reject_remote_clients(true);
|
||||
opts.pipe_mode(PipeMode::Byte);
|
||||
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS);
|
||||
|
||||
opts.reject_remote_clients(false);
|
||||
opts.pipe_mode(PipeMode::Message);
|
||||
assert_eq!(opts.pipe_mode, PIPE_TYPE_MESSAGE);
|
||||
|
||||
opts.reject_remote_clients(true);
|
||||
opts.pipe_mode(PipeMode::Message);
|
||||
assert_eq!(
|
||||
opts.pipe_mode,
|
||||
PIPE_TYPE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
74
zeroidc/vendor/tokio/src/park/either.rs
vendored
74
zeroidc/vendor/tokio/src/park/either.rs
vendored
|
@ -1,74 +0,0 @@
|
|||
#![cfg_attr(not(feature = "full"), allow(dead_code))]
|
||||
|
||||
use crate::park::{Park, Unpark};
|
||||
|
||||
use std::fmt;
|
||||
use std::time::Duration;
|
||||
|
||||
pub(crate) enum Either<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
|
||||
impl<A, B> Park for Either<A, B>
|
||||
where
|
||||
A: Park,
|
||||
B: Park,
|
||||
{
|
||||
type Unpark = Either<A::Unpark, B::Unpark>;
|
||||
type Error = Either<A::Error, B::Error>;
|
||||
|
||||
fn unpark(&self) -> Self::Unpark {
|
||||
match self {
|
||||
Either::A(a) => Either::A(a.unpark()),
|
||||
Either::B(b) => Either::B(b.unpark()),
|
||||
}
|
||||
}
|
||||
|
||||
fn park(&mut self) -> Result<(), Self::Error> {
|
||||
match self {
|
||||
Either::A(a) => a.park().map_err(Either::A),
|
||||
Either::B(b) => b.park().map_err(Either::B),
|
||||
}
|
||||
}
|
||||
|
||||
fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
|
||||
match self {
|
||||
Either::A(a) => a.park_timeout(duration).map_err(Either::A),
|
||||
Either::B(b) => b.park_timeout(duration).map_err(Either::B),
|
||||
}
|
||||
}
|
||||
|
||||
fn shutdown(&mut self) {
|
||||
match self {
|
||||
Either::A(a) => a.shutdown(),
|
||||
Either::B(b) => b.shutdown(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Unpark for Either<A, B>
|
||||
where
|
||||
A: Unpark,
|
||||
B: Unpark,
|
||||
{
|
||||
fn unpark(&self) {
|
||||
match self {
|
||||
Either::A(a) => a.unpark(),
|
||||
Either::B(b) => b.unpark(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> fmt::Debug for Either<A, B>
|
||||
where
|
||||
A: fmt::Debug,
|
||||
B: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Either::A(a) => a.fmt(fmt),
|
||||
Either::B(b) => b.fmt(fmt),
|
||||
}
|
||||
}
|
||||
}
|
117
zeroidc/vendor/tokio/src/park/mod.rs
vendored
117
zeroidc/vendor/tokio/src/park/mod.rs
vendored
|
@ -1,117 +0,0 @@
|
|||
//! Abstraction over blocking and unblocking the current thread.
|
||||
//!
|
||||
//! Provides an abstraction over blocking the current thread. This is similar to
|
||||
//! the park / unpark constructs provided by `std` but made generic. This allows
|
||||
//! embedding custom functionality to perform when the thread is blocked.
|
||||
//!
|
||||
//! A blocked `Park` instance is unblocked by calling `unpark` on its
|
||||
//! `Unpark` handle.
|
||||
//!
|
||||
//! The `ParkThread` struct implements `Park` using `thread::park` to put the
|
||||
//! thread to sleep. The Tokio reactor also implements park, but uses
|
||||
//! `mio::Poll` to block the thread instead.
|
||||
//!
|
||||
//! The `Park` trait is composable. A timer implementation might decorate a
|
||||
//! `Park` implementation by checking if any timeouts have elapsed after the
|
||||
//! inner `Park` implementation unblocks.
|
||||
//!
|
||||
//! # Model
|
||||
//!
|
||||
//! Conceptually, each `Park` instance has an associated token, which is
|
||||
//! initially not present:
|
||||
//!
|
||||
//! * The `park` method blocks the current thread unless or until the token is
|
||||
//! available, at which point it atomically consumes the token.
|
||||
//! * The `unpark` method atomically makes the token available if it wasn't
|
||||
//! already.
|
||||
//!
|
||||
//! Some things to note:
|
||||
//!
|
||||
//! * If `unpark` is called before `park`, the next call to `park` will
|
||||
//! **not** block the thread.
|
||||
//! * **Spurious** wakeups are permitted, i.e., the `park` method may unblock
|
||||
//! even if `unpark` was not called.
|
||||
//! * `park_timeout` does the same as `park` but allows specifying a maximum
|
||||
//! time to block the thread for.
|
||||
|
||||
cfg_rt! {
|
||||
pub(crate) mod either;
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "rt", feature = "sync"))]
|
||||
pub(crate) mod thread;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Blocks the current thread.
|
||||
pub(crate) trait Park {
|
||||
/// Unpark handle type for the `Park` implementation.
|
||||
type Unpark: Unpark;
|
||||
|
||||
/// Error returned by `park`.
|
||||
type Error: Debug;
|
||||
|
||||
/// Gets a new `Unpark` handle associated with this `Park` instance.
|
||||
fn unpark(&self) -> Self::Unpark;
|
||||
|
||||
/// Blocks the current thread unless or until the token is available.
|
||||
///
|
||||
/// A call to `park` does not guarantee that the thread will remain blocked
|
||||
/// forever, and callers should be prepared for this possibility. This
|
||||
/// function may wakeup spuriously for any reason.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function **should** not panic, but ultimately, panics are left as
|
||||
/// an implementation detail. Refer to the documentation for the specific
|
||||
/// `Park` implementation.
|
||||
fn park(&mut self) -> Result<(), Self::Error>;
|
||||
|
||||
/// Parks the current thread for at most `duration`.
|
||||
///
|
||||
/// This function is the same as `park` but allows specifying a maximum time
|
||||
/// to block the thread for.
|
||||
///
|
||||
/// Same as `park`, there is no guarantee that the thread will remain
|
||||
/// blocked for any amount of time. Spurious wakeups are permitted for any
|
||||
/// reason.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function **should** not panic, but ultimately, panics are left as
|
||||
/// an implementation detail. Refer to the documentation for the specific
|
||||
/// `Park` implementation.
|
||||
fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>;
|
||||
|
||||
/// Releases all resources holded by the parker for proper leak-free shutdown.
|
||||
fn shutdown(&mut self);
|
||||
}
|
||||
|
||||
/// Unblock a thread blocked by the associated `Park` instance.
|
||||
pub(crate) trait Unpark: Sync + Send + 'static {
|
||||
/// Unblocks a thread that is blocked by the associated `Park` handle.
|
||||
///
|
||||
/// Calling `unpark` atomically makes available the unpark token, if it is
|
||||
/// not already available.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function **should** not panic, but ultimately, panics are left as
|
||||
/// an implementation detail. Refer to the documentation for the specific
|
||||
/// `Unpark` implementation.
|
||||
fn unpark(&self);
|
||||
}
|
||||
|
||||
impl Unpark for Box<dyn Unpark> {
|
||||
fn unpark(&self) {
|
||||
(**self).unpark()
|
||||
}
|
||||
}
|
||||
|
||||
impl Unpark for Arc<dyn Unpark> {
|
||||
fn unpark(&self) {
|
||||
(**self).unpark()
|
||||
}
|
||||
}
|
66
zeroidc/vendor/tokio/src/process/mod.rs
vendored
66
zeroidc/vendor/tokio/src/process/mod.rs
vendored
|
@ -690,6 +690,36 @@ impl Command {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the process group ID (PGID) of the child process. Equivalent to a
|
||||
/// setpgid call in the child process, but may be more efficient.
|
||||
///
|
||||
/// Process groups determine which processes receive signals.
|
||||
///
|
||||
/// **Note**: This is an [unstable API][unstable] but will be stabilised once
|
||||
/// tokio's MSRV is sufficiently new. See [the documentation on
|
||||
/// unstable features][unstable] for details about using unstable features.
|
||||
///
|
||||
/// If you want similar behaviour without using this unstable feature you can
|
||||
/// create a [`std::process::Command`] and convert that into a
|
||||
/// [`tokio::process::Command`] using the `From` trait.
|
||||
///
|
||||
/// [unstable]: crate#unstable-features
|
||||
/// [`tokio::process::Command`]: crate::process::Command
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::process::Command;
|
||||
///
|
||||
/// let command = Command::new("ls")
|
||||
/// .process_group(0);
|
||||
/// ```
|
||||
#[cfg(unix)]
|
||||
#[cfg(tokio_unstable)]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(unix, tokio_unstable))))]
|
||||
pub fn process_group(&mut self, pgroup: i32) -> &mut Command {
|
||||
self.std.process_group(pgroup);
|
||||
self
|
||||
}
|
||||
|
||||
/// Executes the command as a child process, returning a handle to it.
|
||||
///
|
||||
/// By default, stdin, stdout and stderr are inherited from the parent.
|
||||
|
@ -924,7 +954,7 @@ where
|
|||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// Keep track of task budget
|
||||
let coop = ready!(crate::coop::poll_proceed(cx));
|
||||
let coop = ready!(crate::runtime::coop::poll_proceed(cx));
|
||||
|
||||
let ret = Pin::new(&mut self.inner).poll(cx);
|
||||
|
||||
|
@ -1285,41 +1315,51 @@ impl ChildStderr {
|
|||
|
||||
impl AsyncWrite for ChildStdin {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
self.inner.poll_write(cx, buf)
|
||||
Pin::new(&mut self.inner).poll_write(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.inner).poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.inner).poll_shutdown(cx)
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[io::IoSlice<'_>],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
Pin::new(&mut self.inner).poll_write_vectored(cx, bufs)
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
self.inner.is_write_vectored()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for ChildStdout {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut ReadBuf<'_>,
|
||||
) -> Poll<io::Result<()>> {
|
||||
// Safety: pipes support reading into uninitialized memory
|
||||
unsafe { self.inner.poll_read(cx, buf) }
|
||||
Pin::new(&mut self.inner).poll_read(cx, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for ChildStderr {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut ReadBuf<'_>,
|
||||
) -> Poll<io::Result<()>> {
|
||||
// Safety: pipes support reading into uninitialized memory
|
||||
unsafe { self.inner.poll_read(cx, buf) }
|
||||
Pin::new(&mut self.inner).poll_read(cx, buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
104
zeroidc/vendor/tokio/src/process/unix/mod.rs
vendored
104
zeroidc/vendor/tokio/src/process/unix/mod.rs
vendored
|
@ -21,23 +21,20 @@
|
|||
//! processes in general aren't scalable (e.g. millions) so it shouldn't be that
|
||||
//! bad in theory...
|
||||
|
||||
pub(crate) mod driver;
|
||||
|
||||
pub(crate) mod orphan;
|
||||
use orphan::{OrphanQueue, OrphanQueueImpl, Wait};
|
||||
|
||||
mod reap;
|
||||
use reap::Reaper;
|
||||
|
||||
use crate::io::PollEvented;
|
||||
use crate::io::{AsyncRead, AsyncWrite, PollEvented, ReadBuf};
|
||||
use crate::process::kill::Kill;
|
||||
use crate::process::SpawnedChild;
|
||||
use crate::signal::unix::driver::Handle as SignalHandle;
|
||||
use crate::runtime::signal::Handle as SignalHandle;
|
||||
use crate::signal::unix::{signal, Signal, SignalKind};
|
||||
|
||||
use mio::event::Source;
|
||||
use mio::unix::SourceFd;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::fmt;
|
||||
use std::fs::File;
|
||||
use std::future::Future;
|
||||
|
@ -64,25 +61,41 @@ impl Kill for StdChild {
|
|||
}
|
||||
}
|
||||
|
||||
static ORPHAN_QUEUE: Lazy<OrphanQueueImpl<StdChild>> = Lazy::new(OrphanQueueImpl::new);
|
||||
cfg_not_has_const_mutex_new! {
|
||||
fn get_orphan_queue() -> &'static OrphanQueueImpl<StdChild> {
|
||||
use crate::util::once_cell::OnceCell;
|
||||
|
||||
static ORPHAN_QUEUE: OnceCell<OrphanQueueImpl<StdChild>> = OnceCell::new();
|
||||
|
||||
ORPHAN_QUEUE.get(OrphanQueueImpl::new)
|
||||
}
|
||||
}
|
||||
|
||||
cfg_has_const_mutex_new! {
|
||||
fn get_orphan_queue() -> &'static OrphanQueueImpl<StdChild> {
|
||||
static ORPHAN_QUEUE: OrphanQueueImpl<StdChild> = OrphanQueueImpl::new();
|
||||
|
||||
&ORPHAN_QUEUE
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct GlobalOrphanQueue;
|
||||
|
||||
impl fmt::Debug for GlobalOrphanQueue {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ORPHAN_QUEUE.fmt(fmt)
|
||||
get_orphan_queue().fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalOrphanQueue {
|
||||
fn reap_orphans(handle: &SignalHandle) {
|
||||
ORPHAN_QUEUE.reap_orphans(handle)
|
||||
pub(crate) fn reap_orphans(handle: &SignalHandle) {
|
||||
get_orphan_queue().reap_orphans(handle)
|
||||
}
|
||||
}
|
||||
|
||||
impl OrphanQueue<StdChild> for GlobalOrphanQueue {
|
||||
fn push_orphan(&self, orphan: StdChild) {
|
||||
ORPHAN_QUEUE.push_orphan(orphan)
|
||||
get_orphan_queue().push_orphan(orphan)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,7 +156,7 @@ impl Future for Child {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Pipe {
|
||||
// Actually a pipe and not a File. However, we are reusing `File` to get
|
||||
// Actually a pipe is not a File. However, we are reusing `File` to get
|
||||
// close on drop. This is a similar trick as `mio`.
|
||||
fd: File,
|
||||
}
|
||||
|
@ -169,6 +182,10 @@ impl<'a> io::Write for &'a Pipe {
|
|||
fn flush(&mut self) -> io::Result<()> {
|
||||
(&self.fd).flush()
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
|
||||
(&self.fd).write_vectored(bufs)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Pipe {
|
||||
|
@ -177,8 +194,8 @@ impl AsRawFd for Pipe {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn convert_to_stdio(io: PollEvented<Pipe>) -> io::Result<Stdio> {
|
||||
let mut fd = io.into_inner()?.fd;
|
||||
pub(crate) fn convert_to_stdio(io: ChildStdio) -> io::Result<Stdio> {
|
||||
let mut fd = io.inner.into_inner()?.fd;
|
||||
|
||||
// Ensure that the fd to be inherited is set to *blocking* mode, as this
|
||||
// is the default that virtually all programs expect to have. Those
|
||||
|
@ -213,7 +230,62 @@ impl Source for Pipe {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type ChildStdio = PollEvented<Pipe>;
|
||||
pub(crate) struct ChildStdio {
|
||||
inner: PollEvented<Pipe>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ChildStdio {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for ChildStdio {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for ChildStdio {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
self.inner.poll_write(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[io::IoSlice<'_>],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
self.inner.poll_write_vectored(cx, bufs)
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for ChildStdio {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut ReadBuf<'_>,
|
||||
) -> Poll<io::Result<()>> {
|
||||
// Safety: pipes support reading into uninitialized memory
|
||||
unsafe { self.inner.poll_read(cx, buf) }
|
||||
}
|
||||
}
|
||||
|
||||
fn set_nonblocking<T: AsRawFd>(fd: &mut T, nonblocking: bool) -> io::Result<()> {
|
||||
unsafe {
|
||||
|
@ -238,7 +310,7 @@ fn set_nonblocking<T: AsRawFd>(fd: &mut T, nonblocking: bool) -> io::Result<()>
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn stdio<T>(io: T) -> io::Result<PollEvented<Pipe>>
|
||||
pub(super) fn stdio<T>(io: T) -> io::Result<ChildStdio>
|
||||
where
|
||||
T: IntoRawFd,
|
||||
{
|
||||
|
@ -246,5 +318,5 @@ where
|
|||
let mut pipe = Pipe::from(io);
|
||||
set_nonblocking(&mut pipe, true)?;
|
||||
|
||||
PollEvented::new(pipe)
|
||||
PollEvented::new(pipe).map(|inner| ChildStdio { inner })
|
||||
}
|
||||
|
|
28
zeroidc/vendor/tokio/src/process/unix/orphan.rs
vendored
28
zeroidc/vendor/tokio/src/process/unix/orphan.rs
vendored
|
@ -1,5 +1,5 @@
|
|||
use crate::loom::sync::{Mutex, MutexGuard};
|
||||
use crate::signal::unix::driver::Handle as SignalHandle;
|
||||
use crate::runtime::signal::Handle as SignalHandle;
|
||||
use crate::signal::unix::{signal_with_handle, SignalKind};
|
||||
use crate::sync::watch;
|
||||
use std::io;
|
||||
|
@ -43,10 +43,21 @@ pub(crate) struct OrphanQueueImpl<T> {
|
|||
}
|
||||
|
||||
impl<T> OrphanQueueImpl<T> {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
sigchild: Mutex::new(None),
|
||||
queue: Mutex::new(Vec::new()),
|
||||
cfg_not_has_const_mutex_new! {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
sigchild: Mutex::new(None),
|
||||
queue: Mutex::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_has_const_mutex_new! {
|
||||
pub(crate) const fn new() -> Self {
|
||||
Self {
|
||||
sigchild: Mutex::const_new(None),
|
||||
queue: Mutex::const_new(Vec::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,8 +131,8 @@ where
|
|||
#[cfg(all(test, not(loom)))]
|
||||
pub(crate) mod test {
|
||||
use super::*;
|
||||
use crate::io::driver::Driver as IoDriver;
|
||||
use crate::signal::unix::driver::{Driver as SignalDriver, Handle as SignalHandle};
|
||||
use crate::runtime::io::Driver as IoDriver;
|
||||
use crate::runtime::signal::{Driver as SignalDriver, Handle as SignalHandle};
|
||||
use crate::sync::watch;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::io;
|
||||
|
@ -283,7 +294,8 @@ pub(crate) mod test {
|
|||
#[cfg_attr(miri, ignore)] // Miri does not support epoll.
|
||||
#[test]
|
||||
fn does_not_register_signal_if_queue_empty() {
|
||||
let signal_driver = IoDriver::new().and_then(SignalDriver::new).unwrap();
|
||||
let (io_driver, io_handle) = IoDriver::new(1024).unwrap();
|
||||
let signal_driver = SignalDriver::new(io_driver, &io_handle).unwrap();
|
||||
let handle = signal_driver.handle();
|
||||
|
||||
let orphanage = OrphanQueueImpl::new();
|
||||
|
|
127
zeroidc/vendor/tokio/src/process/windows.rs
vendored
127
zeroidc/vendor/tokio/src/process/windows.rs
vendored
|
@ -15,29 +15,31 @@
|
|||
//! `RegisterWaitForSingleObject` and then wait on the other end of the oneshot
|
||||
//! from then on out.
|
||||
|
||||
use crate::io::PollEvented;
|
||||
use crate::io::{blocking::Blocking, AsyncRead, AsyncWrite, ReadBuf};
|
||||
use crate::process::kill::Kill;
|
||||
use crate::process::SpawnedChild;
|
||||
use crate::sync::oneshot;
|
||||
|
||||
use mio::windows::NamedPipe;
|
||||
use std::fmt;
|
||||
use std::fs::File as StdFile;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
|
||||
use std::os::windows::prelude::{AsRawHandle, IntoRawHandle, RawHandle};
|
||||
use std::pin::Pin;
|
||||
use std::process::Stdio;
|
||||
use std::process::{Child as StdChild, Command as StdCommand, ExitStatus};
|
||||
use std::ptr;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
use winapi::shared::minwindef::{DWORD, FALSE};
|
||||
use winapi::um::handleapi::{DuplicateHandle, INVALID_HANDLE_VALUE};
|
||||
use winapi::um::processthreadsapi::GetCurrentProcess;
|
||||
use winapi::um::threadpoollegacyapiset::UnregisterWaitEx;
|
||||
use winapi::um::winbase::{RegisterWaitForSingleObject, INFINITE};
|
||||
use winapi::um::winnt::{
|
||||
BOOLEAN, DUPLICATE_SAME_ACCESS, HANDLE, PVOID, WT_EXECUTEINWAITTHREAD, WT_EXECUTEONLYONCE,
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use windows_sys::{
|
||||
Win32::Foundation::{
|
||||
DuplicateHandle, BOOLEAN, DUPLICATE_SAME_ACCESS, HANDLE, INVALID_HANDLE_VALUE,
|
||||
},
|
||||
Win32::System::Threading::{
|
||||
GetCurrentProcess, RegisterWaitForSingleObject, UnregisterWaitEx, WT_EXECUTEINWAITTHREAD,
|
||||
WT_EXECUTEONLYONCE,
|
||||
},
|
||||
Win32::System::WindowsProgramming::INFINITE,
|
||||
};
|
||||
|
||||
#[must_use = "futures do nothing unless polled"]
|
||||
|
@ -119,11 +121,11 @@ impl Future for Child {
|
|||
}
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let ptr = Box::into_raw(Box::new(Some(tx)));
|
||||
let mut wait_object = ptr::null_mut();
|
||||
let mut wait_object = 0;
|
||||
let rc = unsafe {
|
||||
RegisterWaitForSingleObject(
|
||||
&mut wait_object,
|
||||
inner.child.as_raw_handle(),
|
||||
inner.child.as_raw_handle() as _,
|
||||
Some(callback),
|
||||
ptr as *mut _,
|
||||
INFINITE,
|
||||
|
@ -162,37 +164,106 @@ impl Drop for Waiting {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe extern "system" fn callback(ptr: PVOID, _timer_fired: BOOLEAN) {
|
||||
unsafe extern "system" fn callback(ptr: *mut std::ffi::c_void, _timer_fired: BOOLEAN) {
|
||||
let complete = &mut *(ptr as *mut Option<oneshot::Sender<()>>);
|
||||
let _ = complete.take().unwrap().send(());
|
||||
}
|
||||
|
||||
pub(crate) type ChildStdio = PollEvented<NamedPipe>;
|
||||
#[derive(Debug)]
|
||||
struct ArcFile(Arc<StdFile>);
|
||||
|
||||
pub(super) fn stdio<T>(io: T) -> io::Result<PollEvented<NamedPipe>>
|
||||
impl io::Read for ArcFile {
|
||||
fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
|
||||
(&*self.0).read(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for ArcFile {
|
||||
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
|
||||
(&*self.0).write(bytes)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
(&*self.0).flush()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ChildStdio {
|
||||
// Used for accessing the raw handle, even if the io version is busy
|
||||
raw: Arc<StdFile>,
|
||||
// For doing I/O operations asynchronously
|
||||
io: Blocking<ArcFile>,
|
||||
}
|
||||
|
||||
impl AsRawHandle for ChildStdio {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.raw.as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for ChildStdio {
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut ReadBuf<'_>,
|
||||
) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.io).poll_read(cx, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for ChildStdio {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Pin::new(&mut self.io).poll_write(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.io).poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.io).poll_shutdown(cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn stdio<T>(io: T) -> io::Result<ChildStdio>
|
||||
where
|
||||
T: IntoRawHandle,
|
||||
{
|
||||
let pipe = unsafe { NamedPipe::from_raw_handle(io.into_raw_handle()) };
|
||||
PollEvented::new(pipe)
|
||||
use std::os::windows::prelude::FromRawHandle;
|
||||
|
||||
let raw = Arc::new(unsafe { StdFile::from_raw_handle(io.into_raw_handle()) });
|
||||
let io = Blocking::new(ArcFile(raw.clone()));
|
||||
Ok(ChildStdio { raw, io })
|
||||
}
|
||||
|
||||
pub(crate) fn convert_to_stdio(io: PollEvented<NamedPipe>) -> io::Result<Stdio> {
|
||||
let named_pipe = io.into_inner()?;
|
||||
pub(crate) fn convert_to_stdio(child_stdio: ChildStdio) -> io::Result<Stdio> {
|
||||
let ChildStdio { raw, io } = child_stdio;
|
||||
drop(io); // Try to drop the Arc count here
|
||||
|
||||
Arc::try_unwrap(raw)
|
||||
.or_else(|raw| duplicate_handle(&*raw))
|
||||
.map(Stdio::from)
|
||||
}
|
||||
|
||||
fn duplicate_handle<T: AsRawHandle>(io: &T) -> io::Result<StdFile> {
|
||||
use std::os::windows::prelude::FromRawHandle;
|
||||
|
||||
// Mio does not implement `IntoRawHandle` for `NamedPipe`, so we'll manually
|
||||
// duplicate the handle here...
|
||||
unsafe {
|
||||
let mut dup_handle = INVALID_HANDLE_VALUE;
|
||||
let cur_proc = GetCurrentProcess();
|
||||
|
||||
let status = DuplicateHandle(
|
||||
cur_proc,
|
||||
named_pipe.as_raw_handle(),
|
||||
io.as_raw_handle() as _,
|
||||
cur_proc,
|
||||
&mut dup_handle,
|
||||
0 as DWORD,
|
||||
FALSE,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS,
|
||||
);
|
||||
|
||||
|
@ -200,6 +271,6 @@ pub(crate) fn convert_to_stdio(io: PollEvented<NamedPipe>) -> io::Result<Stdio>
|
|||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(Stdio::from_raw_handle(dup_handle))
|
||||
Ok(StdFile::from_raw_handle(dup_handle as _))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,19 @@
|
|||
//! compilation.
|
||||
|
||||
mod pool;
|
||||
pub(crate) use pool::{spawn_blocking, BlockingPool, Mandatory, Spawner, Task};
|
||||
pub(crate) use pool::{spawn_blocking, BlockingPool, Spawner};
|
||||
|
||||
cfg_fs! {
|
||||
pub(crate) use pool::spawn_mandatory_blocking;
|
||||
}
|
||||
|
||||
cfg_trace! {
|
||||
pub(crate) use pool::Mandatory;
|
||||
}
|
||||
|
||||
mod schedule;
|
||||
mod shutdown;
|
||||
mod task;
|
||||
pub(crate) use schedule::NoopSchedule;
|
||||
pub(crate) use task::BlockingTask;
|
||||
|
||||
use crate::runtime::Builder;
|
||||
|
|
253
zeroidc/vendor/tokio/src/runtime/blocking/pool.rs
vendored
253
zeroidc/vendor/tokio/src/runtime/blocking/pool.rs
vendored
|
@ -2,15 +2,16 @@
|
|||
|
||||
use crate::loom::sync::{Arc, Condvar, Mutex};
|
||||
use crate::loom::thread;
|
||||
use crate::runtime::blocking::schedule::NoopSchedule;
|
||||
use crate::runtime::blocking::shutdown;
|
||||
use crate::runtime::blocking::schedule::BlockingSchedule;
|
||||
use crate::runtime::blocking::{shutdown, BlockingTask};
|
||||
use crate::runtime::builder::ThreadNameFn;
|
||||
use crate::runtime::context;
|
||||
use crate::runtime::task::{self, JoinHandle};
|
||||
use crate::runtime::{Builder, Callback, ToHandle};
|
||||
use crate::runtime::{Builder, Callback, Handle};
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::Duration;
|
||||
|
||||
pub(crate) struct BlockingPool {
|
||||
|
@ -23,6 +24,53 @@ pub(crate) struct Spawner {
|
|||
inner: Arc<Inner>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct SpawnerMetrics {
|
||||
num_threads: AtomicUsize,
|
||||
num_idle_threads: AtomicUsize,
|
||||
queue_depth: AtomicUsize,
|
||||
}
|
||||
|
||||
impl SpawnerMetrics {
|
||||
fn num_threads(&self) -> usize {
|
||||
self.num_threads.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn num_idle_threads(&self) -> usize {
|
||||
self.num_idle_threads.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
cfg_metrics! {
|
||||
fn queue_depth(&self) -> usize {
|
||||
self.queue_depth.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
fn inc_num_threads(&self) {
|
||||
self.num_threads.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn dec_num_threads(&self) {
|
||||
self.num_threads.fetch_sub(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn inc_num_idle_threads(&self) {
|
||||
self.num_idle_threads.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn dec_num_idle_threads(&self) -> usize {
|
||||
self.num_idle_threads.fetch_sub(1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn inc_queue_depth(&self) {
|
||||
self.queue_depth.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn dec_queue_depth(&self) {
|
||||
self.queue_depth.fetch_sub(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
/// State shared between worker threads.
|
||||
shared: Mutex<Shared>,
|
||||
|
@ -47,12 +95,13 @@ struct Inner {
|
|||
|
||||
// Customizable wait timeout.
|
||||
keep_alive: Duration,
|
||||
|
||||
// Metrics about the pool.
|
||||
metrics: SpawnerMetrics,
|
||||
}
|
||||
|
||||
struct Shared {
|
||||
queue: VecDeque<Task>,
|
||||
num_th: usize,
|
||||
num_idle: u32,
|
||||
num_notify: u32,
|
||||
shutdown: bool,
|
||||
shutdown_tx: Option<shutdown::Sender>,
|
||||
|
@ -71,7 +120,7 @@ struct Shared {
|
|||
}
|
||||
|
||||
pub(crate) struct Task {
|
||||
task: task::UnownedTask<NoopSchedule>,
|
||||
task: task::UnownedTask<BlockingSchedule>,
|
||||
mandatory: Mandatory,
|
||||
}
|
||||
|
||||
|
@ -82,8 +131,27 @@ pub(crate) enum Mandatory {
|
|||
NonMandatory,
|
||||
}
|
||||
|
||||
pub(crate) enum SpawnError {
|
||||
/// Pool is shutting down and the task was not scheduled
|
||||
ShuttingDown,
|
||||
/// There are no worker threads available to take the task
|
||||
/// and the OS failed to spawn a new one
|
||||
NoThreads(io::Error),
|
||||
}
|
||||
|
||||
impl From<SpawnError> for io::Error {
|
||||
fn from(e: SpawnError) -> Self {
|
||||
match e {
|
||||
SpawnError::ShuttingDown => {
|
||||
io::Error::new(io::ErrorKind::Other, "blocking pool shutting down")
|
||||
}
|
||||
SpawnError::NoThreads(e) => e,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub(crate) fn new(task: task::UnownedTask<NoopSchedule>, mandatory: Mandatory) -> Task {
|
||||
pub(crate) fn new(task: task::UnownedTask<BlockingSchedule>, mandatory: Mandatory) -> Task {
|
||||
Task { task, mandatory }
|
||||
}
|
||||
|
||||
|
@ -105,12 +173,13 @@ const KEEP_ALIVE: Duration = Duration::from_secs(10);
|
|||
/// Tasks will be scheduled as non-mandatory, meaning they may not get executed
|
||||
/// in case of runtime shutdown.
|
||||
#[track_caller]
|
||||
#[cfg_attr(tokio_wasi, allow(dead_code))]
|
||||
pub(crate) fn spawn_blocking<F, R>(func: F) -> JoinHandle<R>
|
||||
where
|
||||
F: FnOnce() -> R + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let rt = context::current();
|
||||
let rt = Handle::current();
|
||||
rt.spawn_blocking(func)
|
||||
}
|
||||
|
||||
|
@ -128,8 +197,8 @@ cfg_fs! {
|
|||
F: FnOnce() -> R + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let rt = context::current();
|
||||
rt.as_inner().spawn_mandatory_blocking(&rt, func)
|
||||
let rt = Handle::current();
|
||||
rt.inner.blocking_spawner().spawn_mandatory_blocking(&rt, func)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,8 +214,6 @@ impl BlockingPool {
|
|||
inner: Arc::new(Inner {
|
||||
shared: Mutex::new(Shared {
|
||||
queue: VecDeque::new(),
|
||||
num_th: 0,
|
||||
num_idle: 0,
|
||||
num_notify: 0,
|
||||
shutdown: false,
|
||||
shutdown_tx: Some(shutdown_tx),
|
||||
|
@ -161,6 +228,7 @@ impl BlockingPool {
|
|||
before_stop: builder.before_stop.clone(),
|
||||
thread_cap,
|
||||
keep_alive,
|
||||
metrics: Default::default(),
|
||||
}),
|
||||
},
|
||||
shutdown_rx,
|
||||
|
@ -220,7 +288,104 @@ impl fmt::Debug for BlockingPool {
|
|||
// ===== impl Spawner =====
|
||||
|
||||
impl Spawner {
|
||||
pub(crate) fn spawn(&self, task: Task, rt: &dyn ToHandle) -> Result<(), ()> {
|
||||
#[track_caller]
|
||||
pub(crate) fn spawn_blocking<F, R>(&self, rt: &Handle, func: F) -> JoinHandle<R>
|
||||
where
|
||||
F: FnOnce() -> R + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let (join_handle, spawn_result) =
|
||||
if cfg!(debug_assertions) && std::mem::size_of::<F>() > 2048 {
|
||||
self.spawn_blocking_inner(Box::new(func), Mandatory::NonMandatory, None, rt)
|
||||
} else {
|
||||
self.spawn_blocking_inner(func, Mandatory::NonMandatory, None, rt)
|
||||
};
|
||||
|
||||
match spawn_result {
|
||||
Ok(()) => join_handle,
|
||||
// Compat: do not panic here, return the join_handle even though it will never resolve
|
||||
Err(SpawnError::ShuttingDown) => join_handle,
|
||||
Err(SpawnError::NoThreads(e)) => {
|
||||
panic!("OS can't spawn worker thread: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_fs! {
|
||||
#[track_caller]
|
||||
#[cfg_attr(any(
|
||||
all(loom, not(test)), // the function is covered by loom tests
|
||||
test
|
||||
), allow(dead_code))]
|
||||
pub(crate) fn spawn_mandatory_blocking<F, R>(&self, rt: &Handle, func: F) -> Option<JoinHandle<R>>
|
||||
where
|
||||
F: FnOnce() -> R + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let (join_handle, spawn_result) = if cfg!(debug_assertions) && std::mem::size_of::<F>() > 2048 {
|
||||
self.spawn_blocking_inner(
|
||||
Box::new(func),
|
||||
Mandatory::Mandatory,
|
||||
None,
|
||||
rt,
|
||||
)
|
||||
} else {
|
||||
self.spawn_blocking_inner(
|
||||
func,
|
||||
Mandatory::Mandatory,
|
||||
None,
|
||||
rt,
|
||||
)
|
||||
};
|
||||
|
||||
if spawn_result.is_ok() {
|
||||
Some(join_handle)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn spawn_blocking_inner<F, R>(
|
||||
&self,
|
||||
func: F,
|
||||
is_mandatory: Mandatory,
|
||||
name: Option<&str>,
|
||||
rt: &Handle,
|
||||
) -> (JoinHandle<R>, Result<(), SpawnError>)
|
||||
where
|
||||
F: FnOnce() -> R + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let fut = BlockingTask::new(func);
|
||||
let id = task::Id::next();
|
||||
#[cfg(all(tokio_unstable, feature = "tracing"))]
|
||||
let fut = {
|
||||
use tracing::Instrument;
|
||||
let location = std::panic::Location::caller();
|
||||
let span = tracing::trace_span!(
|
||||
target: "tokio::task::blocking",
|
||||
"runtime.spawn",
|
||||
kind = %"blocking",
|
||||
task.name = %name.unwrap_or_default(),
|
||||
task.id = id.as_u64(),
|
||||
"fn" = %std::any::type_name::<F>(),
|
||||
spawn.location = %format_args!("{}:{}:{}", location.file(), location.line(), location.column()),
|
||||
);
|
||||
fut.instrument(span)
|
||||
};
|
||||
|
||||
#[cfg(not(all(tokio_unstable, feature = "tracing")))]
|
||||
let _ = name;
|
||||
|
||||
let (task, handle) = task::unowned(fut, BlockingSchedule::new(rt), id);
|
||||
|
||||
let spawned = self.spawn_task(Task::new(task, is_mandatory), rt);
|
||||
(handle, spawned)
|
||||
}
|
||||
|
||||
fn spawn_task(&self, task: Task, rt: &Handle) -> Result<(), SpawnError> {
|
||||
let mut shared = self.inner.shared.lock();
|
||||
|
||||
if shared.shutdown {
|
||||
|
@ -230,15 +395,16 @@ impl Spawner {
|
|||
task.task.shutdown();
|
||||
|
||||
// no need to even push this task; it would never get picked up
|
||||
return Err(());
|
||||
return Err(SpawnError::ShuttingDown);
|
||||
}
|
||||
|
||||
shared.queue.push_back(task);
|
||||
self.inner.metrics.inc_queue_depth();
|
||||
|
||||
if shared.num_idle == 0 {
|
||||
if self.inner.metrics.num_idle_threads() == 0 {
|
||||
// No threads are able to process the task.
|
||||
|
||||
if shared.num_th == self.inner.thread_cap {
|
||||
if self.inner.metrics.num_threads() == self.inner.thread_cap {
|
||||
// At max number of threads
|
||||
} else {
|
||||
assert!(shared.shutdown_tx.is_some());
|
||||
|
@ -249,11 +415,14 @@ impl Spawner {
|
|||
|
||||
match self.spawn_thread(shutdown_tx, rt, id) {
|
||||
Ok(handle) => {
|
||||
shared.num_th += 1;
|
||||
self.inner.metrics.inc_num_threads();
|
||||
shared.worker_thread_index += 1;
|
||||
shared.worker_threads.insert(id, handle);
|
||||
}
|
||||
Err(ref e) if is_temporary_os_thread_error(e) && shared.num_th > 0 => {
|
||||
Err(ref e)
|
||||
if is_temporary_os_thread_error(e)
|
||||
&& self.inner.metrics.num_threads() > 0 =>
|
||||
{
|
||||
// OS temporarily failed to spawn a new thread.
|
||||
// The task will be picked up eventually by a currently
|
||||
// busy thread.
|
||||
|
@ -261,7 +430,7 @@ impl Spawner {
|
|||
Err(e) => {
|
||||
// The OS refused to spawn the thread and there is no thread
|
||||
// to pick up the task that has just been pushed to the queue.
|
||||
panic!("OS can't spawn worker thread: {}", e)
|
||||
return Err(SpawnError::NoThreads(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +441,7 @@ impl Spawner {
|
|||
// exactly. Thread libraries may generate spurious
|
||||
// wakeups, this counter is used to keep us in a
|
||||
// consistent state.
|
||||
shared.num_idle -= 1;
|
||||
self.inner.metrics.dec_num_idle_threads();
|
||||
shared.num_notify += 1;
|
||||
self.inner.condvar.notify_one();
|
||||
}
|
||||
|
@ -283,7 +452,7 @@ impl Spawner {
|
|||
fn spawn_thread(
|
||||
&self,
|
||||
shutdown_tx: shutdown::Sender,
|
||||
rt: &dyn ToHandle,
|
||||
rt: &Handle,
|
||||
id: usize,
|
||||
) -> std::io::Result<thread::JoinHandle<()>> {
|
||||
let mut builder = thread::Builder::new().name((self.inner.thread_name)());
|
||||
|
@ -292,17 +461,33 @@ impl Spawner {
|
|||
builder = builder.stack_size(stack_size);
|
||||
}
|
||||
|
||||
let rt = rt.to_handle();
|
||||
let rt = rt.clone();
|
||||
|
||||
builder.spawn(move || {
|
||||
// Only the reference should be moved into the closure
|
||||
let _enter = crate::runtime::context::enter(rt.clone());
|
||||
rt.as_inner().blocking_spawner.inner.run(id);
|
||||
let _enter = rt.enter();
|
||||
rt.inner.blocking_spawner().inner.run(id);
|
||||
drop(shutdown_tx);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
cfg_metrics! {
|
||||
impl Spawner {
|
||||
pub(crate) fn num_threads(&self) -> usize {
|
||||
self.inner.metrics.num_threads()
|
||||
}
|
||||
|
||||
pub(crate) fn num_idle_threads(&self) -> usize {
|
||||
self.inner.metrics.num_idle_threads()
|
||||
}
|
||||
|
||||
pub(crate) fn queue_depth(&self) -> usize {
|
||||
self.inner.metrics.queue_depth()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tells whether the error when spawning a thread is temporary.
|
||||
#[inline]
|
||||
fn is_temporary_os_thread_error(error: &std::io::Error) -> bool {
|
||||
|
@ -321,6 +506,7 @@ impl Inner {
|
|||
'main: loop {
|
||||
// BUSY
|
||||
while let Some(task) = shared.queue.pop_front() {
|
||||
self.metrics.dec_queue_depth();
|
||||
drop(shared);
|
||||
task.run();
|
||||
|
||||
|
@ -328,7 +514,7 @@ impl Inner {
|
|||
}
|
||||
|
||||
// IDLE
|
||||
shared.num_idle += 1;
|
||||
self.metrics.inc_num_idle_threads();
|
||||
|
||||
while !shared.shutdown {
|
||||
let lock_result = self.condvar.wait_timeout(shared, self.keep_alive).unwrap();
|
||||
|
@ -362,6 +548,7 @@ impl Inner {
|
|||
if shared.shutdown {
|
||||
// Drain the queue
|
||||
while let Some(task) = shared.queue.pop_front() {
|
||||
self.metrics.dec_queue_depth();
|
||||
drop(shared);
|
||||
|
||||
task.shutdown_or_run_if_mandatory();
|
||||
|
@ -372,7 +559,7 @@ impl Inner {
|
|||
// Work was produced, and we "took" it (by decrementing num_notify).
|
||||
// This means that num_idle was decremented once for our wakeup.
|
||||
// But, since we are exiting, we need to "undo" that, as we'll stay idle.
|
||||
shared.num_idle += 1;
|
||||
self.metrics.inc_num_idle_threads();
|
||||
// NOTE: Technically we should also do num_notify++ and notify again,
|
||||
// but since we're shutting down anyway, that won't be necessary.
|
||||
break;
|
||||
|
@ -380,17 +567,17 @@ impl Inner {
|
|||
}
|
||||
|
||||
// Thread exit
|
||||
shared.num_th -= 1;
|
||||
self.metrics.dec_num_threads();
|
||||
|
||||
// num_idle should now be tracked exactly, panic
|
||||
// with a descriptive message if it is not the
|
||||
// case.
|
||||
shared.num_idle = shared
|
||||
.num_idle
|
||||
.checked_sub(1)
|
||||
.expect("num_idle underflowed on thread exit");
|
||||
let prev_idle = self.metrics.dec_num_idle_threads();
|
||||
if prev_idle < self.metrics.num_idle_threads() {
|
||||
panic!("num_idle_threads underflowed on thread exit")
|
||||
}
|
||||
|
||||
if shared.shutdown && shared.num_th == 0 {
|
||||
if shared.shutdown && self.metrics.num_threads() == 0 {
|
||||
self.condvar.notify_one();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,52 @@
|
|||
#[cfg(feature = "test-util")]
|
||||
use crate::runtime::scheduler;
|
||||
use crate::runtime::task::{self, Task};
|
||||
use crate::runtime::Handle;
|
||||
|
||||
/// `task::Schedule` implementation that does nothing. This is unique to the
|
||||
/// blocking scheduler as tasks scheduled are not really futures but blocking
|
||||
/// operations.
|
||||
/// `task::Schedule` implementation that does nothing (except some bookkeeping
|
||||
/// in test-util builds). This is unique to the blocking scheduler as tasks
|
||||
/// scheduled are not really futures but blocking operations.
|
||||
///
|
||||
/// We avoid storing the task by forgetting it in `bind` and re-materializing it
|
||||
/// in `release.
|
||||
pub(crate) struct NoopSchedule;
|
||||
/// in `release`.
|
||||
pub(crate) struct BlockingSchedule {
|
||||
#[cfg(feature = "test-util")]
|
||||
handle: Handle,
|
||||
}
|
||||
|
||||
impl task::Schedule for NoopSchedule {
|
||||
impl BlockingSchedule {
|
||||
#[cfg_attr(not(feature = "test-util"), allow(unused_variables))]
|
||||
pub(crate) fn new(handle: &Handle) -> Self {
|
||||
#[cfg(feature = "test-util")]
|
||||
{
|
||||
match &handle.inner {
|
||||
scheduler::Handle::CurrentThread(handle) => {
|
||||
handle.driver.clock.inhibit_auto_advance();
|
||||
}
|
||||
#[cfg(all(feature = "rt-multi-thread", not(tokio_wasi)))]
|
||||
scheduler::Handle::MultiThread(_) => {}
|
||||
}
|
||||
}
|
||||
BlockingSchedule {
|
||||
#[cfg(feature = "test-util")]
|
||||
handle: handle.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl task::Schedule for BlockingSchedule {
|
||||
fn release(&self, _task: &Task<Self>) -> Option<Task<Self>> {
|
||||
#[cfg(feature = "test-util")]
|
||||
{
|
||||
match &self.handle.inner {
|
||||
scheduler::Handle::CurrentThread(handle) => {
|
||||
handle.driver.clock.allow_auto_advance();
|
||||
handle.driver.unpark();
|
||||
}
|
||||
#[cfg(all(feature = "rt-multi-thread", not(tokio_wasi)))]
|
||||
scheduler::Handle::MultiThread(_) => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue