Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
2024-01-08 01:21:28 +04:00
parent 5ecd8cf2cb
commit 1b6a04ca55
7309 changed files with 2160054 additions and 0 deletions

1
vendor/flume/.cargo-checksum.json vendored Normal file
View File

@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"378edfec4dde51dee9c0d1e8285d88b3d218cb9b8b42ffa3e27405661c23b0b6","Cargo.lock":"cc14608e4a0c130f6f898cc6187e3b8964639f6c960bc9c08589dcac06506526","Cargo.toml":"6246515094dda94c71890606c39275b555aed886b5f4c789eb362ce7b1eea40f","LICENSE-APACHE":"d8621ec2eee5b9ca3c65f8492505f3590de8574fac0fdf5132a77232dba47abc","LICENSE-MIT":"30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652","README.md":"48f7ca4326cfcd3440931e5c82fc21f7b8a6f40041bc94be817c291ad71b6c5b","benches/basic.rs":"61ecb5f7c092b82382cc20e73ca84677dd4973cc358ea6bff15f92fda227b481","examples/async.rs":"7a0bb8848d94bd1fa9a857ffba0b3fbea6d57d7058ed65d2a7cbcf8518ec8652","examples/perf.rs":"52b67c619932a283ad9109c5fe5b47d32f7d3e7533356170047b686dfac330c9","examples/select.rs":"7659b015889545a59b9bce046fc353fea7bcaa9d54cb59f6bd5c002e15872909","examples/simple.rs":"f96d308b808b5fd66ca03dac9f09c13e5f13141992698551503415a411f6596a","src/async.rs":"851b0db2f8115eb222a9eb3c39d3dcdd8699c5b8e757580f26a03ca71c88d0e4","src/lib.rs":"36f84973b6bb45e54161dfb8eb574b30bace69d4b382e7fe8669d5636473d9ea","src/select.rs":"940cbdfbb26b9a2811bf42df3b26f1a619bd71896b8a6b6f2cdbb350c4fab270","src/signal.rs":"20a1732fdbfe888b9a25438bf16a185393f18fb1ad795926fae969c6817fe43b","tests/after.rs":"53e17263eab8eb733f575e4d1d43e054c6d22556d36e105f3f87c4cfb891880c","tests/array.rs":"2b071429d678e07ca52b79b4792120816a1ec7e64afd29c5781ddddbbbd7888b","tests/async.rs":"45bce43e990694578cf03c27dcf112df8d9ec1806e7c1be866885d76bb5abf85","tests/basic.rs":"0606408fe5ff1512839d43cc5c5f6a98c1e09fe919b5ad843643b5019926100b","tests/check_same_channel.rs":"e9e313d1ada50ac0ab0b9bcf19b901efd8cc226902edac62a8d573cea54e06ca","tests/golang.rs":"9e821cefd322a2353b288c7368902028daca643648da2e223ec1174c0e93e4ef","tests/iter.rs":"82d4f7acd20c9b10d2623211e71f5b6c37e4dafda2e13c871008c03995d76ced","tests/list.rs":"5885ee800d5c93b410d3bfa12d834fd817fd3362bca15a08b0aa7f84de58432e","tests/method_sharing.rs":"4d6c867e689254840ecbb1ae8a70ab3226d45bf92282e3bd2681c83726983ffa","tests/mpsc.rs":"965e18abbfcdebec09380f8ec9bb62e5556ad2aa0176ed088ce091994c1d2500","tests/never.rs":"cb838011c6f39c150c67e6836eb880300d53c22a2ea0312cdec999efb779ca29","tests/ready.rs":"5e1234ce49e8cbf89ec4f28bd2f4fe10641891bf6a7915d2fef6f9ab0c343997","tests/same_channel.rs":"71524e90dc364cc2c8085a9517757abe55f59a25b95600029abb283bc8677ad9","tests/select.rs":"67f8a647a7976f0d77673f4cc8d03b74690f3e8578c47e1bc64caeab68dd7df7","tests/select_macro.rs":"32793ac9775879e72ae3ce3975aa87f7407c6e7023d3d85f50f06a3ac5e308a3","tests/stream.rs":"c6d9500813d7216fd514f35dadb1b7b58282def553f40d76b37032221bb05cd6","tests/thread_locals.rs":"ad92e07a4ef5c3dd8b6ff8620161ab93963b3de241a680db551f2be60c8e3853","tests/tick.rs":"35fabd118073decf0cd830e9245c77a1a2e19227f7b4f73d239589728a591601","tests/zero.rs":"23a15a51681596716d5882242cd2c8cd0925c6ea2d0ef289f80775f3f2d6d10c"},"package":"55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"}

134
vendor/flume/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,134 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# Unreleased
### Added
### Removed
### Changed
### Fixed
# [0.11.0] - 2023-08-16
### Added
- `WeakSender`, a sender that doesn't keep the channel open
- `Sender/Receiver::sender_count/receiver_count`, a way to query the number of senders and receivers attached to a channel
- `Sender/Receiver::same_channel`, a way to determine whether senders and receivers are attached to the same channel
### Changed
- Relaxed some API features
- Make all remaining spinlocks opt-in
### Fixed
- Fixed a rare race condition in the async implementation
# [0.10.14] - 2022-07-21
### Fixed
- Fixed unbounded memory usage in `RecvFut::poll_inner`
# [0.10.13] - 2022-06-10
### Added
- `SendSink::sender`, to get the sender of a `SendSink`
# [0.10.12] - 2022-03-10
### Changed
- Updated `nanorand` to 0.7
# [0.10.11] - 2022-02-14
### Fixed
- Out-of-order bug when using channels asynchronously
# [0.10.10] - 2022-01-11
### Added
- `From<SendError>` and `From<RecvError>` impls for other error types
- Marked futures as `#[must_use]`
### Changes
- Switched to scheduler-driven locking by default, with a `spin` feature to reenable the old behaviour
- Minor doc improvements
# [0.10.9] - 2021-08-25
### Changed
- Switched from `spinning_top` to `spin`
# [0.10.8] - 2021-08-06
### Changed
- Updated `nanorand` to `0.6`
# [0.10.7] - 2021-06-10
### Fixed
- Removed accidental nightly-only syntax
# [0.10.6] - 2021-06-10
### Added
- `fn into_inner(self) -> T` for send errors, allowing for easy access to the unsent message
# [0.10.5] - 2021-04-26
### Added
- `is_disconnected`, `is_empty`, `is_full`, `len`, and `capacity` on future types
# [0.10.4] - 2021-04-12
### Fixed
- Shutdown-related race condition with async recv that caused spurious errors
# [0.10.3] - 2021-04-09
### Fixed
- Compilation error when enabling `select` without `eventual_fairness`
# [0.10.2] - 2021-02-07
### Fixed
- Incorrect pointer comparison in `Selector` causing missing receives
# [0.10.1] - 2020-12-30
### Removed
- Removed `T: Unpin` requirement from async traits using `pin_project`
# [0.10.0] - 2020-12-09
### Changed
- Renamed `SendFuture` to `SendFut` to be consistent with `RecvFut`
- Improved async-related documentation
### Fixed
- Updated `nanorand` to address security advisory

1312
vendor/flume/Cargo.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

110
vendor/flume/Cargo.toml vendored Normal file
View File

@ -0,0 +1,110 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "flume"
version = "0.11.0"
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>"]
exclude = [
"/.github",
"/misc",
]
description = "A blazingly fast multi-producer channel"
documentation = "https://docs.rs/flume"
readme = "README.md"
keywords = [
"mpsc",
"fifo",
"channel",
"thread",
"mpmc",
]
categories = [
"concurrency",
"data-structures",
]
license = "Apache-2.0/MIT"
repository = "https://github.com/zesterer/flume"
[[bench]]
name = "basic"
harness = false
[dependencies.futures-core]
version = "0.3"
optional = true
default_features = false
[dependencies.futures-sink]
version = "0.3"
optional = true
default_features = false
[dependencies.nanorand]
version = "0.7"
features = ["getrandom"]
optional = true
[dependencies.spin1]
version = "0.9.8"
features = ["mutex"]
package = "spin"
[dev-dependencies.async-std]
version = "1.9.0"
features = [
"attributes",
"unstable",
]
[dev-dependencies.criterion]
version = "0.3.4"
[dev-dependencies.crossbeam-channel]
version = "0.5.5"
[dev-dependencies.crossbeam-utils]
version = "0.8.10"
[dev-dependencies.futures]
version = "^0.3"
features = ["std"]
[dev-dependencies.rand]
version = "0.8.3"
[dev-dependencies.tokio]
version = "^1.16.1"
features = [
"rt",
"macros",
]
[dev-dependencies.waker-fn]
version = "1.1.0"
[features]
async = [
"futures-sink",
"futures-core",
]
default = [
"async",
"select",
"eventual-fairness",
]
eventual-fairness = [
"select",
"nanorand",
]
select = []
spin = []

201
vendor/flume/LICENSE-APACHE vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

23
vendor/flume/LICENSE-MIT vendored Normal file
View File

@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

86
vendor/flume/README.md vendored Normal file
View File

@ -0,0 +1,86 @@
# Flume
A blazingly fast multi-producer, multi-consumer channel.
[![Cargo](https://img.shields.io/crates/v/flume.svg)](
https://crates.io/crates/flume)
[![Documentation](https://docs.rs/flume/badge.svg)](
https://docs.rs/flume)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](
https://github.com/zesterer/flume)
![actions-badge](https://github.com/zesterer/flume/workflows/Rust/badge.svg?branch=master)
```rust
use std::thread;
fn main() {
println!("Hello, world!");
let (tx, rx) = flume::unbounded();
thread::spawn(move || {
(0..10).for_each(|i| {
tx.send(i).unwrap();
})
});
let received: u32 = rx.iter().sum();
assert_eq!((0..10).sum::<u32>(), received);
}
```
## Why Flume?
- **Featureful**: Unbounded, bounded and rendezvous queues
- **Fast**: Always faster than `std::sync::mpsc` and sometimes `crossbeam-channel`
- **Safe**: No `unsafe` code anywhere in the codebase!
- **Flexible**: `Sender` and `Receiver` both implement `Send + Sync + Clone`
- **Familiar**: Drop-in replacement for `std::sync::mpsc`
- **Capable**: Additional features like MPMC support and send timeouts/deadlines
- **Simple**: Few dependencies, minimal codebase, fast to compile
- **Asynchronous**: `async` support, including mix 'n match with sync code
- **Ergonomic**: Powerful `select`-like interface
## Usage
To use Flume, place the following line under the `[dependencies]` section in your `Cargo.toml`:
```toml
flume = "x.y"
```
## Cargo Features
Flume comes with several optional features:
- `spin`: use spinlocks instead of OS-level synchronisation primitives internally for some kind of data access (may be more performant on a small number of platforms for specific workloads)
- `select`: Adds support for the [`Selector`](https://docs.rs/flume/latest/flume/select/struct.Selector.html) API, allowing a thread to wait on several channels/operations at once
- `async`: Adds support for the [async API](https://docs.rs/flume/latest/flume/async/index.html), including on otherwise synchronous channels
- `eventual-fairness`: Use randomness in the implementation of `Selector` to avoid biasing/saturating certain events over others
You can enable these features by changing the dependency in your `Cargo.toml` like so:
```toml
flume = { version = "x.y", default-features = false, features = ["async", "select"] }
```
## [Benchmarks](https://what-if.xkcd.com/147/)
Although Flume has its own extensive benchmarks, don't take it from here that Flume is quick.
The following graph is from the `crossbeam-channel` benchmark suite.
Tests were performed on an AMD Ryzen 7 3700x with 8/16 cores running Linux kernel 5.11.2 with the bfq scheduler.
# <img src="misc/benchmarks.png" alt="Flume benchmarks (crossbeam benchmark suite)" width="100%"/>
## License
Flume is licensed under either of:
- Apache License 2.0, (http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (http://opensource.org/licenses/MIT)

474
vendor/flume/benches/basic.rs vendored Normal file
View File

@ -0,0 +1,474 @@
#[macro_use]
extern crate criterion;
use std::{
sync::mpsc,
thread,
fmt::Debug,
};
use criterion::{Criterion, Bencher, black_box};
use std::time::Instant;
trait Sender: Clone + Send + Sized + 'static {
type Item: Debug + Default;
type BoundedSender: Sender<Item=Self::Item>;
type Receiver: Receiver<Item=Self::Item>;
fn unbounded() -> (Self, Self::Receiver);
fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver);
fn send(&self, msg: Self::Item);
}
trait Receiver: Send + Sized + 'static {
type Item: Default;
fn recv(&self) -> Self::Item;
fn iter(&self) -> Box<dyn Iterator<Item=Self::Item> + '_>;
}
impl<T: Send + Debug + Default + 'static> Sender for flume::Sender<T> {
type Item = T;
type BoundedSender = Self;
type Receiver = flume::Receiver<T>;
fn unbounded() -> (Self, Self::Receiver) {
flume::unbounded()
}
fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver) {
flume::bounded(n)
}
fn send(&self, msg: T) {
flume::Sender::send(self, msg).unwrap();
}
}
impl<T: Send + Default + 'static> Receiver for flume::Receiver<T> {
type Item = T;
fn recv(&self) -> Self::Item {
flume::Receiver::recv(self).unwrap()
}
fn iter(&self) -> Box<dyn Iterator<Item=T> + '_> {
Box::new(std::iter::from_fn(move || flume::Receiver::recv(self).ok()))
}
}
impl<T: Send + Debug + Default + 'static> Sender for crossbeam_channel::Sender<T> {
type Item = T;
type BoundedSender = Self;
type Receiver = crossbeam_channel::Receiver<T>;
fn unbounded() -> (Self, Self::Receiver) {
crossbeam_channel::unbounded()
}
fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver) {
crossbeam_channel::bounded(n)
}
fn send(&self, msg: T) {
crossbeam_channel::Sender::send(self, msg).unwrap();
}
}
impl<T: Send + Default + 'static> Receiver for crossbeam_channel::Receiver<T> {
type Item = T;
fn recv(&self) -> Self::Item {
crossbeam_channel::Receiver::recv(self).unwrap()
}
fn iter(&self) -> Box<dyn Iterator<Item=T> + '_> {
Box::new(crossbeam_channel::Receiver::iter(self))
}
}
impl<T: Send + Debug + Default + 'static> Sender for mpsc::Sender<T> {
type Item = T;
type BoundedSender = mpsc::SyncSender<T>;
type Receiver = mpsc::Receiver<T>;
fn unbounded() -> (Self, Self::Receiver) {
mpsc::channel()
}
fn bounded(n: usize) -> (Self::BoundedSender, Self::Receiver) {
mpsc::sync_channel(n)
}
fn send(&self, msg: T) {
mpsc::Sender::send(self, msg).unwrap();
}
}
impl<T: Send + Debug + Default + 'static> Sender for mpsc::SyncSender<T> {
type Item = T;
type BoundedSender = Self;
type Receiver = mpsc::Receiver<T>;
fn unbounded() -> (Self, Self::Receiver) { unimplemented!() }
fn bounded(_: usize) -> (Self::BoundedSender, Self::Receiver) { unimplemented!() }
fn send(&self, msg: T) {
mpsc::SyncSender::send(self, msg).unwrap();
}
}
impl<T: Send + Default + 'static> Receiver for mpsc::Receiver<T> {
type Item = T;
fn recv(&self) -> Self::Item {
mpsc::Receiver::recv(self).unwrap()
}
fn iter(&self) -> Box<dyn Iterator<Item=T> + '_> {
Box::new(mpsc::Receiver::iter(self))
}
}
fn test_create<S: Sender>(b: &mut Bencher) {
b.iter(|| S::unbounded());
}
fn test_oneshot<S: Sender>(b: &mut Bencher) {
b.iter(|| {
let (tx, rx) = S::unbounded();
tx.send(Default::default());
black_box(rx.recv());
});
}
fn test_inout<S: Sender>(b: &mut Bencher) {
let (tx, rx) = S::unbounded();
b.iter(|| {
tx.send(Default::default());
black_box(rx.recv());
});
}
fn test_hydra<S: Sender>(b: &mut Bencher, thread_num: usize, msg_num: usize) {
let (main_tx, main_rx) = S::unbounded();
let mut txs = Vec::new();
for _ in 0..thread_num {
let main_tx = main_tx.clone();
let (tx, rx) = S::unbounded();
txs.push(tx);
thread::spawn(move || {
for msg in rx.iter() {
main_tx.send(msg);
}
});
}
drop(main_tx);
b.iter(|| {
for tx in &txs {
for _ in 0..msg_num {
tx.send(Default::default());
}
}
for _ in 0..thread_num {
for _ in 0..msg_num {
black_box(main_rx.recv());
}
}
});
}
fn test_kitsune<S: Sender>(b: &mut Bencher, thread_num: usize, msg_num: usize)
where S::Receiver: Clone
{
let (out_tx, out_rx) = S::unbounded();
let (in_tx, in_rx) = S::unbounded();
for _ in 0..thread_num {
let in_tx = in_tx.clone();
let out_rx = out_rx.clone();
thread::spawn(move || {
for msg in out_rx.iter() {
in_tx.send(msg);
}
});
}
b.iter(|| {
for _ in 0..thread_num {
for _ in 0..msg_num {
out_tx.send(Default::default());
}
}
for _ in 0..thread_num {
for _ in 0..msg_num {
black_box(in_rx.recv());
}
}
});
}
fn test_robin_u<S: Sender>(b: &mut Bencher, thread_num: usize, msg_num: usize) {
let (mut main_tx, main_rx) = S::unbounded();
for _ in 0..thread_num {
let (mut tx, rx) = S::unbounded();
std::mem::swap(&mut tx, &mut main_tx);
thread::spawn(move || {
for msg in rx.iter() {
tx.send(msg);
}
});
}
b.iter(|| {
for _ in 0..msg_num {
main_tx.send(Default::default());
}
for _ in 0..msg_num {
black_box(main_rx.recv());
}
});
}
fn test_robin_b<S: Sender>(b: &mut Bencher, thread_num: usize, msg_num: usize) {
let (mut main_tx, main_rx) = S::bounded(1);
for _ in 0..thread_num {
let (mut tx, rx) = S::bounded(1);
std::mem::swap(&mut tx, &mut main_tx);
thread::spawn(move || {
for msg in rx.iter() {
tx.send(msg);
}
});
}
b.iter(|| {
let main_tx = main_tx.clone();
thread::spawn(move || {
for _ in 0..msg_num {
main_tx.send(Default::default());
}
});
for _ in 0..msg_num {
black_box(main_rx.recv());
}
});
}
fn test_mpsc_bounded_no_wait<S: Sender>(b: &mut Bencher, thread_num: u64) {
b.iter_custom(|iters| {
let iters = iters * 1000;
let (tx, rx) = S::bounded(iters as usize);
let start = Instant::now();
crossbeam_utils::thread::scope(|scope| {
for _ in 0..thread_num {
let tx = tx.clone();
scope.spawn(move |_| {
for _ in 0..iters / thread_num {
tx.send(Default::default());
}
});
}
for _ in 0..iters - ((iters / thread_num) * thread_num) {
tx.send(Default::default());
}
for _ in 0..iters {
black_box(rx.recv());
}
})
.unwrap();
start.elapsed()
})
}
fn test_mpsc_bounded<S: Sender>(b: &mut Bencher, bound: usize, thread_num: usize) {
b.iter_custom(|iters| {
let (tx, rx) = S::bounded(bound);
let start = Instant::now();
crossbeam_utils::thread::scope(|scope| {
let msgs = iters as usize * bound.max(1);
for _ in 0..thread_num {
let tx = tx.clone();
scope.spawn(move |_| {
for _ in 0..msgs / thread_num as usize {
tx.send(Default::default());
}
});
}
scope.spawn(move |_| {
// Remainder
for _ in 0..msgs - (msgs / thread_num as usize * thread_num) {
tx.send(Default::default());
}
});
for _ in 0..msgs {
black_box(rx.recv());
}
})
.unwrap();
start.elapsed()
})
}
fn create(b: &mut Criterion) {
b.bench_function("create-flume", |b| test_create::<flume::Sender<u32>>(b));
b.bench_function("create-crossbeam", |b| test_create::<crossbeam_channel::Sender<u32>>(b));
b.bench_function("create-std", |b| test_create::<mpsc::Sender<u32>>(b));
}
fn oneshot(b: &mut Criterion) {
b.bench_function("oneshot-flume", |b| test_oneshot::<flume::Sender<u32>>(b));
b.bench_function("oneshot-crossbeam", |b| test_oneshot::<crossbeam_channel::Sender<u32>>(b));
b.bench_function("oneshot-std", |b| test_oneshot::<mpsc::Sender<u32>>(b));
}
fn inout(b: &mut Criterion) {
b.bench_function("inout-flume", |b| test_inout::<flume::Sender<u32>>(b));
b.bench_function("inout-crossbeam", |b| test_inout::<crossbeam_channel::Sender<u32>>(b));
b.bench_function("inout-std", |b| test_inout::<mpsc::Sender<u32>>(b));
}
fn hydra_32t_1m(b: &mut Criterion) {
b.bench_function("hydra-32t-1m-flume", |b| test_hydra::<flume::Sender<u32>>(b, 32, 1));
b.bench_function("hydra-32t-1m-crossbeam", |b| test_hydra::<crossbeam_channel::Sender<u32>>(b, 32, 1));
b.bench_function("hydra-32t-1m-std", |b| test_hydra::<mpsc::Sender<u32>>(b, 32, 1));
}
fn hydra_32t_1000m(b: &mut Criterion) {
b.bench_function("hydra-32t-1000m-flume", |b| test_hydra::<flume::Sender<u32>>(b, 32, 1000));
b.bench_function("hydra-32t-1000m-crossbeam", |b| test_hydra::<crossbeam_channel::Sender<u32>>(b, 32, 1000));
b.bench_function("hydra-32t-1000m-std", |b| test_hydra::<mpsc::Sender<u32>>(b, 32, 1000));
}
fn hydra_256t_1m(b: &mut Criterion) {
b.bench_function("hydra-256t-1m-flume", |b| test_hydra::<flume::Sender<u32>>(b, 256, 1));
b.bench_function("hydra-256t-1m-crossbeam", |b| test_hydra::<crossbeam_channel::Sender<u32>>(b, 256, 1));
b.bench_function("hydra-256t-1m-std", |b| test_hydra::<mpsc::Sender<u32>>(b, 256, 1));
}
fn hydra_1t_1000m(b: &mut Criterion) {
b.bench_function("hydra-1t-1000m-flume", |b| test_hydra::<flume::Sender<u32>>(b, 1, 1000));
b.bench_function("hydra-1t-1000m-crossbeam", |b| test_hydra::<crossbeam_channel::Sender<u32>>(b, 1, 1000));
b.bench_function("hydra-1t-1000m-std", |b| test_hydra::<mpsc::Sender<u32>>(b, 1, 1000));
}
fn hydra_4t_10000m(b: &mut Criterion) {
b.bench_function("hydra-4t-10000m-flume", |b| test_hydra::<flume::Sender<u32>>(b, 4, 10000));
b.bench_function("hydra-4t-10000m-crossbeam", |b| test_hydra::<crossbeam_channel::Sender<u32>>(b, 4, 10000));
b.bench_function("hydra-4t-10000m-std", |b| test_hydra::<mpsc::Sender<u32>>(b, 4, 10000));
}
fn kitsune_32t_1m(b: &mut Criterion) {
b.bench_function("kitsune-32t-1m-flume", |b| test_kitsune::<flume::Sender<u32>>(b, 32, 1));
b.bench_function("kitsune-32t-1m-crossbeam", |b| test_kitsune::<crossbeam_channel::Sender<u32>>(b, 32, 1));
//b.bench_function("kitsune-32t-1m-std", |b| test_kitsune::<mpsc::Sender<u32>>(b, 32, 1));
}
fn kitsune_32t_1000m(b: &mut Criterion) {
b.bench_function("kitsune-32t-1000m-flume", |b| test_kitsune::<flume::Sender<u32>>(b, 32, 1000));
b.bench_function("kitsune-32t-1000m-crossbeam", |b| test_kitsune::<crossbeam_channel::Sender<u32>>(b, 32, 1000));
//b.bench_function("kitsune-32t-1000m-std", |b| test_kitsune::<mpsc::Sender<u32>>(b, 32, 1000));
}
fn kitsune_256t_1m(b: &mut Criterion) {
b.bench_function("kitsune-256t-1m-flume", |b| test_kitsune::<flume::Sender<u32>>(b, 256, 1));
b.bench_function("kitsune-256t-1m-crossbeam", |b| test_kitsune::<crossbeam_channel::Sender<u32>>(b, 256, 1));
//b.bench_function("kitsune-256t-1m-std", |b| test_kitsune::<mpsc::Sender<u32>>(b, 256, 1));
}
fn kitsune_1t_1000m(b: &mut Criterion) {
b.bench_function("kitsune-1t-1000m-flume", |b| test_kitsune::<flume::Sender<u32>>(b, 1, 1000));
b.bench_function("kitsune-1t-1000m-crossbeam", |b| test_kitsune::<crossbeam_channel::Sender<u32>>(b, 1, 1000));
//b.bench_function("kitsune-1t-1000m-std", |b| test_kitsune::<mpsc::Sender<u32>>(b, 1, 1000));
}
fn kitsune_4t_10000m(b: &mut Criterion) {
b.bench_function("kitsune-4t-10000m-flume", |b| test_kitsune::<flume::Sender<u32>>(b, 4, 10000));
b.bench_function("kitsune-4t-10000m-crossbeam", |b| test_kitsune::<crossbeam_channel::Sender<u32>>(b, 4, 10000));
//b.bench_function("kitsune-4t-10000m-std", |b| test_kitsune::<mpsc::Sender<u32>>(b, 4, 10000));
}
fn robin_u_32t_1m(b: &mut Criterion) {
b.bench_function("robin-u-32t-1m-flume", |b| test_robin_u::<flume::Sender<u32>>(b, 32, 1));
b.bench_function("robin-u-32t-1m-crossbeam", |b| test_robin_u::<crossbeam_channel::Sender<u32>>(b, 32, 1));
b.bench_function("robin-u-32t-1m-std", |b| test_robin_u::<mpsc::Sender<u32>>(b, 32, 1));
}
fn robin_u_4t_1000m(b: &mut Criterion) {
b.bench_function("robin-u-4t-1000m-flume", |b| test_robin_u::<flume::Sender<u32>>(b, 4, 1000));
b.bench_function("robin-u-4t-1000m-crossbeam", |b| test_robin_u::<crossbeam_channel::Sender<u32>>(b, 4, 1000));
b.bench_function("robin-u-4t-1000m-std", |b| test_robin_u::<mpsc::Sender<u32>>(b, 4, 1000));
}
fn robin_b_32t_16m(b: &mut Criterion) {
b.bench_function("robin-b-32t-16m-flume", |b| test_robin_b::<flume::Sender<u32>>(b, 32, 16));
b.bench_function("robin-b-32t-16m-crossbeam", |b| test_robin_b::<crossbeam_channel::Sender<u32>>(b, 32, 16));
b.bench_function("robin-b-32t-16m-std", |b| test_robin_b::<mpsc::Sender<u32>>(b, 32, 16));
}
fn robin_b_4t_1000m(b: &mut Criterion) {
b.bench_function("robin-b-4t-1000m-flume", |b| test_robin_b::<flume::Sender<u32>>(b, 4, 1000));
b.bench_function("robin-b-4t-1000m-crossbeam", |b| test_robin_b::<crossbeam_channel::Sender<u32>>(b, 4, 1000));
b.bench_function("robin-b-4t-1000m-std", |b| test_robin_b::<mpsc::Sender<u32>>(b, 4, 1000));
}
fn mpsc_bounded_no_wait_4t(b: &mut Criterion) {
b.bench_function("mpsc-bounded-no-wait-4t-flume", |b| test_mpsc_bounded_no_wait::<flume::Sender<u32>>(b, 4));
b.bench_function("mpsc-bounded-no-wait-4t-crossbeam", |b| test_mpsc_bounded_no_wait::<crossbeam_channel::Sender<u32>>(b, 4));
b.bench_function("mpsc-bounded-no-wait-4t-std", |b| test_mpsc_bounded_no_wait::<mpsc::Sender<u32>>(b, 4));
}
fn mpsc_bounded_4t(b: &mut Criterion) {
for bound in &[0, 1, 10, 50, 10_000] {
let text = format!("mpsc-bounded-small-4t-{}m-", bound);
let bound = *bound;
b.bench_function(&format!("{}{}", text, "flume"), |b| test_mpsc_bounded::<flume::Sender<u32>>(b, bound, 4));
b.bench_function(&format!("{}{}", text, "crossbeam"), |b| test_mpsc_bounded::<crossbeam_channel::Sender<u32>>(b, bound, 4));
b.bench_function(&format!("{}{}", text, "std"), |b| test_mpsc_bounded::<mpsc::Sender<u32>>(b, bound, 4));
}
}
criterion_group!(
compare,
create,
oneshot,
inout,
hydra_32t_1m,
hydra_32t_1000m,
hydra_256t_1m,
hydra_1t_1000m,
hydra_4t_10000m,
robin_b_32t_16m,
robin_b_4t_1000m,
robin_u_32t_1m,
robin_u_4t_1000m,
mpsc_bounded_no_wait_4t,
mpsc_bounded_4t,
kitsune_32t_1m,
kitsune_32t_1000m,
kitsune_256t_1m,
kitsune_1t_1000m,
kitsune_4t_10000m,
);
criterion_main!(compare);

21
vendor/flume/examples/async.rs vendored Normal file
View File

@ -0,0 +1,21 @@
#[cfg(feature = "async")]
#[async_std::main]
async fn main() {
let (tx, rx) = flume::bounded(1);
let t = async_std::task::spawn(async move {
while let Ok(msg) = rx.recv_async().await {
println!("Received: {}", msg);
}
});
tx.send_async("Hello, world!").await.unwrap();
tx.send_async("How are you today?").await.unwrap();
drop(tx);
t.await;
}
#[cfg(not(feature = "async"))]
fn main() {}

30
vendor/flume/examples/perf.rs vendored Normal file
View File

@ -0,0 +1,30 @@
fn main() {
let thread_num = 32;
let msg_num = 16;
let (mut main_tx, main_rx) = flume::bounded::<()>(1);
for _ in 0..thread_num {
let (mut tx, rx) = flume::bounded(1);
std::mem::swap(&mut tx, &mut main_tx);
std::thread::spawn(move || {
for msg in rx.iter() {
tx.send(msg).unwrap();
}
});
}
for _ in 0..1000 {
let main_tx = main_tx.clone();
std::thread::spawn(move || {
for _ in 0..msg_num {
main_tx.send(Default::default()).unwrap();
}
});
for _ in 0..msg_num {
main_rx.recv().unwrap();
}
}
}

25
vendor/flume/examples/select.rs vendored Normal file
View File

@ -0,0 +1,25 @@
#[cfg(feature = "select")]
use flume::Selector;
#[cfg(feature = "select")]
fn main() {
// Create two channels
let (red_tx, red_rx) = flume::unbounded();
let (blue_tx, blue_rx) = flume::unbounded();
// Spawn two threads that each send a message into their respective channel
std::thread::spawn(move || { let _ = red_tx.send("Red"); });
std::thread::spawn(move || { let _ = blue_tx.send("Blue"); });
// Race them to see which one sends their message first
let winner = Selector::new()
.recv(&red_rx, |msg| msg)
.recv(&blue_rx, |msg| msg)
.wait()
.unwrap();
println!("{} won!", winner);
}
#[cfg(not(feature = "select"))]
fn main() {}

18
vendor/flume/examples/simple.rs vendored Normal file
View File

@ -0,0 +1,18 @@
use std::thread;
fn main() {
let (tx, rx) = flume::unbounded();
let t = thread::spawn(move || {
for msg in rx.iter() {
println!("Received: {}", msg);
}
});
tx.send("Hello, world!").unwrap();
tx.send("How are you today?").unwrap();
drop(tx);
t.join().unwrap();
}

543
vendor/flume/src/async.rs vendored Normal file
View File

@ -0,0 +1,543 @@
//! Futures and other types that allow asynchronous interaction with channels.
use std::{
future::Future,
pin::Pin,
task::{Context, Poll, Waker},
any::Any,
ops::Deref,
};
use crate::*;
use futures_core::{stream::{Stream, FusedStream}, future::FusedFuture};
use futures_sink::Sink;
use spin1::Mutex as Spinlock;
struct AsyncSignal {
waker: Spinlock<Waker>,
woken: AtomicBool,
stream: bool,
}
impl AsyncSignal {
fn new(cx: &Context, stream: bool) -> Self {
AsyncSignal {
waker: Spinlock::new(cx.waker().clone()),
woken: AtomicBool::new(false),
stream,
}
}
}
impl Signal for AsyncSignal {
fn fire(&self) -> bool {
self.woken.store(true, Ordering::SeqCst);
self.waker.lock().wake_by_ref();
self.stream
}
fn as_any(&self) -> &(dyn Any + 'static) { self }
fn as_ptr(&self) -> *const () { self as *const _ as *const () }
}
impl<T> Hook<T, AsyncSignal> {
// Update the hook to point to the given Waker.
// Returns whether the hook has been previously awakened
fn update_waker(&self, cx_waker: &Waker) -> bool {
let mut waker = self.1.waker.lock();
let woken = self.1.woken.load(Ordering::SeqCst);
if !waker.will_wake(cx_waker) {
*waker = cx_waker.clone();
// Avoid the edge case where the waker was woken just before the wakers were
// swapped.
if woken {
cx_waker.wake_by_ref();
}
}
woken
}
}
#[derive(Clone)]
enum OwnedOrRef<'a, T> {
Owned(T),
Ref(&'a T),
}
impl<'a, T> Deref for OwnedOrRef<'a, T> {
type Target = T;
fn deref(&self) -> &T {
match self {
OwnedOrRef::Owned(arc) => &arc,
OwnedOrRef::Ref(r) => r,
}
}
}
impl<T> Sender<T> {
/// Asynchronously send a value into the channel, returning an error if all receivers have been
/// dropped. If the channel is bounded and is full, the returned future will yield to the async
/// runtime.
///
/// In the current implementation, the returned future will not yield to the async runtime if the
/// channel is unbounded. This may change in later versions.
pub fn send_async(&self, item: T) -> SendFut<T> {
SendFut {
sender: OwnedOrRef::Ref(&self),
hook: Some(SendState::NotYetSent(item)),
}
}
/// Convert this sender into a future that asynchronously sends a single message into the channel,
/// returning an error if all receivers have been dropped. If the channel is bounded and is full,
/// this future will yield to the async runtime.
///
/// In the current implementation, the returned future will not yield to the async runtime if the
/// channel is unbounded. This may change in later versions.
pub fn into_send_async<'a>(self, item: T) -> SendFut<'a, T> {
SendFut {
sender: OwnedOrRef::Owned(self),
hook: Some(SendState::NotYetSent(item)),
}
}
/// Create an asynchronous sink that uses this sender to asynchronously send messages into the
/// channel. The sender will continue to be usable after the sink has been dropped.
///
/// In the current implementation, the returned sink will not yield to the async runtime if the
/// channel is unbounded. This may change in later versions.
pub fn sink(&self) -> SendSink<'_, T> {
SendSink(SendFut {
sender: OwnedOrRef::Ref(&self),
hook: None,
})
}
/// Convert this sender into a sink that allows asynchronously sending messages into the channel.
///
/// In the current implementation, the returned sink will not yield to the async runtime if the
/// channel is unbounded. This may change in later versions.
pub fn into_sink<'a>(self) -> SendSink<'a, T> {
SendSink(SendFut {
sender: OwnedOrRef::Owned(self),
hook: None,
})
}
}
enum SendState<T> {
NotYetSent(T),
QueuedItem(Arc<Hook<T, AsyncSignal>>),
}
/// A future that sends a value into a channel.
///
/// Can be created via [`Sender::send_async`] or [`Sender::into_send_async`].
#[must_use = "futures/streams/sinks do nothing unless you `.await` or poll them"]
pub struct SendFut<'a, T> {
sender: OwnedOrRef<'a, Sender<T>>,
// Only none after dropping
hook: Option<SendState<T>>,
}
impl<T> std::marker::Unpin for SendFut<'_, T> {}
impl<'a, T> SendFut<'a, T> {
/// Reset the hook, clearing it and removing it from the waiting sender's queue. This is called
/// on drop and just before `start_send` in the `Sink` implementation.
fn reset_hook(&mut self) {
if let Some(SendState::QueuedItem(hook)) = self.hook.take() {
let hook: Arc<Hook<T, dyn Signal>> = hook;
wait_lock(&self.sender.shared.chan).sending
.as_mut()
.unwrap().1
.retain(|s| s.signal().as_ptr() != hook.signal().as_ptr());
}
}
/// See [`Sender::is_disconnected`].
pub fn is_disconnected(&self) -> bool {
self.sender.is_disconnected()
}
/// See [`Sender::is_empty`].
pub fn is_empty(&self) -> bool {
self.sender.is_empty()
}
/// See [`Sender::is_full`].
pub fn is_full(&self) -> bool {
self.sender.is_full()
}
/// See [`Sender::len`].
pub fn len(&self) -> usize {
self.sender.len()
}
/// See [`Sender::capacity`].
pub fn capacity(&self) -> Option<usize> {
self.sender.capacity()
}
}
impl<'a, T> Drop for SendFut<'a, T> {
fn drop(&mut self) {
self.reset_hook()
}
}
impl<'a, T> Future for SendFut<'a, T> {
type Output = Result<(), SendError<T>>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if let Some(SendState::QueuedItem(hook)) = self.hook.as_ref() {
if hook.is_empty() {
Poll::Ready(Ok(()))
} else if self.sender.shared.is_disconnected() {
let item = hook.try_take();
self.hook = None;
match item {
Some(item) => Poll::Ready(Err(SendError(item))),
None => Poll::Ready(Ok(())),
}
} else {
hook.update_waker(cx.waker());
Poll::Pending
}
} else if let Some(SendState::NotYetSent(item)) = self.hook.take() {
let this = self.get_mut();
let (shared, this_hook) = (&this.sender.shared, &mut this.hook);
shared.send(
// item
item,
// should_block
true,
// make_signal
|msg| Hook::slot(Some(msg), AsyncSignal::new(cx, false)),
// do_block
|hook| {
*this_hook = Some(SendState::QueuedItem(hook));
Poll::Pending
},
)
.map(|r| r.map_err(|err| match err {
TrySendTimeoutError::Disconnected(msg) => SendError(msg),
_ => unreachable!(),
}))
} else { // Nothing to do
Poll::Ready(Ok(()))
}
}
}
impl<'a, T> FusedFuture for SendFut<'a, T> {
fn is_terminated(&self) -> bool {
self.sender.shared.is_disconnected()
}
}
/// A sink that allows sending values into a channel.
///
/// Can be created via [`Sender::sink`] or [`Sender::into_sink`].
pub struct SendSink<'a, T>(SendFut<'a, T>);
impl<'a, T> SendSink<'a, T> {
/// Returns a clone of a sending half of the channel of this sink.
pub fn sender(&self) -> &Sender<T> {
&self.0.sender
}
/// See [`Sender::is_disconnected`].
pub fn is_disconnected(&self) -> bool {
self.0.is_disconnected()
}
/// See [`Sender::is_empty`].
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// See [`Sender::is_full`].
pub fn is_full(&self) -> bool {
self.0.is_full()
}
/// See [`Sender::len`].
pub fn len(&self) -> usize {
self.0.len()
}
/// See [`Sender::capacity`].
pub fn capacity(&self) -> Option<usize> {
self.0.capacity()
}
/// Returns whether the SendSinks are belong to the same channel.
pub fn same_channel(&self, other: &Self) -> bool {
self.sender().same_channel(other.sender())
}
}
impl<'a, T> Sink<T> for SendSink<'a, T> {
type Error = SendError<T>;
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Pin::new(&mut self.0).poll(cx)
}
fn start_send(mut self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> {
self.0.reset_hook();
self.0.hook = Some(SendState::NotYetSent(item));
Ok(())
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Pin::new(&mut self.0).poll(cx) // TODO: A different strategy here?
}
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Pin::new(&mut self.0).poll(cx) // TODO: A different strategy here?
}
}
impl<'a, T> Clone for SendSink<'a, T> {
fn clone(&self) -> SendSink<'a, T> {
SendSink(SendFut {
sender: self.0.sender.clone(),
hook: None,
})
}
}
impl<T> Receiver<T> {
/// Asynchronously receive a value from the channel, returning an error if all senders have been
/// dropped. If the channel is empty, the returned future will yield to the async runtime.
pub fn recv_async(&self) -> RecvFut<'_, T> {
RecvFut::new(OwnedOrRef::Ref(self))
}
/// Convert this receiver into a future that asynchronously receives a single message from the
/// channel, returning an error if all senders have been dropped. If the channel is empty, this
/// future will yield to the async runtime.
pub fn into_recv_async<'a>(self) -> RecvFut<'a, T> {
RecvFut::new(OwnedOrRef::Owned(self))
}
/// Create an asynchronous stream that uses this receiver to asynchronously receive messages
/// from the channel. The receiver will continue to be usable after the stream has been dropped.
pub fn stream(&self) -> RecvStream<'_, T> {
RecvStream(RecvFut::new(OwnedOrRef::Ref(self)))
}
/// Convert this receiver into a stream that allows asynchronously receiving messages from the channel.
pub fn into_stream<'a>(self) -> RecvStream<'a, T> {
RecvStream(RecvFut::new(OwnedOrRef::Owned(self)))
}
}
/// A future which allows asynchronously receiving a message.
///
/// Can be created via [`Receiver::recv_async`] or [`Receiver::into_recv_async`].
#[must_use = "futures/streams/sinks do nothing unless you `.await` or poll them"]
pub struct RecvFut<'a, T> {
receiver: OwnedOrRef<'a, Receiver<T>>,
hook: Option<Arc<Hook<T, AsyncSignal>>>,
}
impl<'a, T> RecvFut<'a, T> {
fn new(receiver: OwnedOrRef<'a, Receiver<T>>) -> Self {
Self {
receiver,
hook: None,
}
}
/// Reset the hook, clearing it and removing it from the waiting receivers queue and waking
/// another receiver if this receiver has been woken, so as not to cause any missed wakeups.
/// This is called on drop and after a new item is received in `Stream::poll_next`.
fn reset_hook(&mut self) {
if let Some(hook) = self.hook.take() {
let hook: Arc<Hook<T, dyn Signal>> = hook;
let mut chan = wait_lock(&self.receiver.shared.chan);
// We'd like to use `Arc::ptr_eq` here but it doesn't seem to work consistently with wide pointers?
chan.waiting.retain(|s| s.signal().as_ptr() != hook.signal().as_ptr());
if hook.signal().as_any().downcast_ref::<AsyncSignal>().unwrap().woken.load(Ordering::SeqCst) {
// If this signal has been fired, but we're being dropped (and so not listening to it),
// pass the signal on to another receiver
chan.try_wake_receiver_if_pending();
}
}
}
fn poll_inner(
self: Pin<&mut Self>,
cx: &mut Context,
stream: bool,
) -> Poll<Result<T, RecvError>> {
if self.hook.is_some() {
match self.receiver.shared.recv_sync(None) {
Ok(msg) => return Poll::Ready(Ok(msg)),
Err(TryRecvTimeoutError::Disconnected) => {
return Poll::Ready(Err(RecvError::Disconnected))
}
_ => (),
}
let hook = self.hook.as_ref().map(Arc::clone).unwrap();
if hook.update_waker(cx.waker()) {
// If the previous hook was awakened, we need to insert it back to the
// queue, otherwise, it remains valid.
wait_lock(&self.receiver.shared.chan)
.waiting
.push_back(hook);
}
// To avoid a missed wakeup, re-check disconnect status here because the channel might have
// gotten shut down before we had a chance to push our hook
if self.receiver.shared.is_disconnected() {
// And now, to avoid a race condition between the first recv attempt and the disconnect check we
// just performed, attempt to recv again just in case we missed something.
Poll::Ready(
self.receiver
.shared
.recv_sync(None)
.map(Ok)
.unwrap_or(Err(RecvError::Disconnected)),
)
} else {
Poll::Pending
}
} else {
let mut_self = self.get_mut();
let (shared, this_hook) = (&mut_self.receiver.shared, &mut mut_self.hook);
shared.recv(
// should_block
true,
// make_signal
|| Hook::trigger(AsyncSignal::new(cx, stream)),
// do_block
|hook| {
*this_hook = Some(hook);
Poll::Pending
},
)
.map(|r| r.map_err(|err| match err {
TryRecvTimeoutError::Disconnected => RecvError::Disconnected,
_ => unreachable!(),
}))
}
}
/// See [`Receiver::is_disconnected`].
pub fn is_disconnected(&self) -> bool {
self.receiver.is_disconnected()
}
/// See [`Receiver::is_empty`].
pub fn is_empty(&self) -> bool {
self.receiver.is_empty()
}
/// See [`Receiver::is_full`].
pub fn is_full(&self) -> bool {
self.receiver.is_full()
}
/// See [`Receiver::len`].
pub fn len(&self) -> usize {
self.receiver.len()
}
/// See [`Receiver::capacity`].
pub fn capacity(&self) -> Option<usize> {
self.receiver.capacity()
}
}
impl<'a, T> Drop for RecvFut<'a, T> {
fn drop(&mut self) {
self.reset_hook();
}
}
impl<'a, T> Future for RecvFut<'a, T> {
type Output = Result<T, RecvError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.poll_inner(cx, false) // stream = false
}
}
impl<'a, T> FusedFuture for RecvFut<'a, T> {
fn is_terminated(&self) -> bool {
self.receiver.shared.is_disconnected() && self.receiver.shared.is_empty()
}
}
/// A stream which allows asynchronously receiving messages.
///
/// Can be created via [`Receiver::stream`] or [`Receiver::into_stream`].
pub struct RecvStream<'a, T>(RecvFut<'a, T>);
impl<'a, T> RecvStream<'a, T> {
/// See [`Receiver::is_disconnected`].
pub fn is_disconnected(&self) -> bool {
self.0.is_disconnected()
}
/// See [`Receiver::is_empty`].
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// See [`Receiver::is_full`].
pub fn is_full(&self) -> bool {
self.0.is_full()
}
/// See [`Receiver::len`].
pub fn len(&self) -> usize {
self.0.len()
}
/// See [`Receiver::capacity`].
pub fn capacity(&self) -> Option<usize> {
self.0.capacity()
}
/// Returns whether the SendSinks are belong to the same channel.
pub fn same_channel(&self, other: &Self) -> bool {
self.0.receiver.same_channel(&*other.0.receiver)
}
}
impl<'a, T> Clone for RecvStream<'a, T> {
fn clone(&self) -> RecvStream<'a, T> {
RecvStream(RecvFut::new(self.0.receiver.clone()))
}
}
impl<'a, T> Stream for RecvStream<'a, T> {
type Item = T;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.0).poll_inner(cx, true) { // stream = true
Poll::Pending => Poll::Pending,
Poll::Ready(item) => {
self.0.reset_hook();
Poll::Ready(item.ok())
}
}
}
}
impl<'a, T> FusedStream for RecvStream<'a, T> {
fn is_terminated(&self) -> bool {
self.0.is_terminated()
}
}

1142
vendor/flume/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

405
vendor/flume/src/select.rs vendored Normal file
View File

@ -0,0 +1,405 @@
//! Types that permit waiting upon multiple blocking operations using the [`Selector`] interface.
use crate::*;
use spin1::Mutex as Spinlock;
use std::{any::Any, marker::PhantomData};
#[cfg(feature = "eventual-fairness")]
use nanorand::Rng;
// A unique token corresponding to an event in a selector
type Token = usize;
struct SelectSignal(
thread::Thread,
Token,
AtomicBool,
Arc<Spinlock<VecDeque<Token>>>,
);
impl Signal for SelectSignal {
fn fire(&self) -> bool {
self.2.store(true, Ordering::SeqCst);
self.3.lock().push_back(self.1);
self.0.unpark();
false
}
fn as_any(&self) -> &(dyn Any + 'static) {
self
}
fn as_ptr(&self) -> *const () {
self as *const _ as *const ()
}
}
trait Selection<'a, T> {
fn init(&mut self) -> Option<T>;
fn poll(&mut self) -> Option<T>;
fn deinit(&mut self);
}
/// An error that may be emitted when attempting to wait for a value on a receiver.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SelectError {
/// A timeout occurred when waiting on a `Selector`.
Timeout,
}
impl fmt::Display for SelectError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SelectError::Timeout => "timeout occurred".fmt(f),
}
}
}
impl std::error::Error for SelectError {}
/// A type used to wait upon multiple blocking operations at once.
///
/// A [`Selector`] implements [`select`](https://en.wikipedia.org/wiki/Select_(Unix))-like behaviour,
/// allowing a thread to wait upon the result of more than one operation at once.
///
/// # Examples
/// ```
/// let (tx0, rx0) = flume::unbounded();
/// let (tx1, rx1) = flume::unbounded();
///
/// std::thread::spawn(move || {
/// tx0.send(true).unwrap();
/// tx1.send(42).unwrap();
/// });
///
/// flume::Selector::new()
/// .recv(&rx0, |b| println!("Received {:?}", b))
/// .recv(&rx1, |n| println!("Received {:?}", n))
/// .wait();
/// ```
pub struct Selector<'a, T: 'a> {
selections: Vec<Box<dyn Selection<'a, T> + 'a>>,
next_poll: usize,
signalled: Arc<Spinlock<VecDeque<Token>>>,
#[cfg(feature = "eventual-fairness")]
rng: nanorand::WyRand,
phantom: PhantomData<*const ()>,
}
impl<'a, T: 'a> Default for Selector<'a, T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T: 'a> fmt::Debug for Selector<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Selector").finish()
}
}
impl<'a, T> Selector<'a, T> {
/// Create a new selector.
pub fn new() -> Self {
Self {
selections: Vec::new(),
next_poll: 0,
signalled: Arc::default(),
phantom: PhantomData::default(),
#[cfg(feature = "eventual-fairness")]
rng: nanorand::WyRand::new(),
}
}
/// Add a send operation to the selector that sends the provided value.
///
/// Once added, the selector can be used to run the provided handler function on completion of this operation.
pub fn send<U, F: FnMut(Result<(), SendError<U>>) -> T + 'a>(
mut self,
sender: &'a Sender<U>,
msg: U,
mapper: F,
) -> Self {
struct SendSelection<'a, T, F, U> {
sender: &'a Sender<U>,
msg: Option<U>,
token: Token,
signalled: Arc<Spinlock<VecDeque<Token>>>,
hook: Option<Arc<Hook<U, SelectSignal>>>,
mapper: F,
phantom: PhantomData<T>,
}
impl<'a, T, F, U> Selection<'a, T> for SendSelection<'a, T, F, U>
where
F: FnMut(Result<(), SendError<U>>) -> T,
{
fn init(&mut self) -> Option<T> {
let token = self.token;
let signalled = self.signalled.clone();
let r = self.sender.shared.send(
self.msg.take().unwrap(),
true,
|msg| {
Hook::slot(
Some(msg),
SelectSignal(
thread::current(),
token,
AtomicBool::new(false),
signalled,
),
)
},
// Always runs
|h| {
self.hook = Some(h);
Ok(())
},
);
if self.hook.is_none() {
Some((self.mapper)(match r {
Ok(()) => Ok(()),
Err(TrySendTimeoutError::Disconnected(msg)) => Err(SendError(msg)),
_ => unreachable!(),
}))
} else {
None
}
}
fn poll(&mut self) -> Option<T> {
let res = if self.sender.shared.is_disconnected() {
// Check the hook one last time
if let Some(msg) = self.hook.as_ref()?.try_take() {
Err(SendError(msg))
} else {
Ok(())
}
} else if self.hook.as_ref().unwrap().is_empty() {
// The message was sent
Ok(())
} else {
return None;
};
Some((&mut self.mapper)(res))
}
fn deinit(&mut self) {
if let Some(hook) = self.hook.take() {
// Remove hook
let hook: Arc<Hook<U, dyn Signal>> = hook;
wait_lock(&self.sender.shared.chan)
.sending
.as_mut()
.unwrap()
.1
.retain(|s| s.signal().as_ptr() != hook.signal().as_ptr());
}
}
}
let token = self.selections.len();
self.selections.push(Box::new(SendSelection {
sender,
msg: Some(msg),
token,
signalled: self.signalled.clone(),
hook: None,
mapper,
phantom: Default::default(),
}));
self
}
/// Add a receive operation to the selector.
///
/// Once added, the selector can be used to run the provided handler function on completion of this operation.
pub fn recv<U, F: FnMut(Result<U, RecvError>) -> T + 'a>(
mut self,
receiver: &'a Receiver<U>,
mapper: F,
) -> Self {
struct RecvSelection<'a, T, F, U> {
receiver: &'a Receiver<U>,
token: Token,
signalled: Arc<Spinlock<VecDeque<Token>>>,
hook: Option<Arc<Hook<U, SelectSignal>>>,
mapper: F,
received: bool,
phantom: PhantomData<T>,
}
impl<'a, T, F, U> Selection<'a, T> for RecvSelection<'a, T, F, U>
where
F: FnMut(Result<U, RecvError>) -> T,
{
fn init(&mut self) -> Option<T> {
let token = self.token;
let signalled = self.signalled.clone();
let r = self.receiver.shared.recv(
true,
|| {
Hook::trigger(SelectSignal(
thread::current(),
token,
AtomicBool::new(false),
signalled,
))
},
// Always runs
|h| {
self.hook = Some(h);
Err(TryRecvTimeoutError::Timeout)
},
);
if self.hook.is_none() {
Some((self.mapper)(match r {
Ok(msg) => Ok(msg),
Err(TryRecvTimeoutError::Disconnected) => Err(RecvError::Disconnected),
_ => unreachable!(),
}))
} else {
None
}
}
fn poll(&mut self) -> Option<T> {
let res = if let Ok(msg) = self.receiver.try_recv() {
self.received = true;
Ok(msg)
} else if self.receiver.shared.is_disconnected() {
Err(RecvError::Disconnected)
} else {
return None;
};
Some((&mut self.mapper)(res))
}
fn deinit(&mut self) {
if let Some(hook) = self.hook.take() {
// Remove hook
let hook: Arc<Hook<U, dyn Signal>> = hook;
wait_lock(&self.receiver.shared.chan)
.waiting
.retain(|s| s.signal().as_ptr() != hook.signal().as_ptr());
// If we were woken, but never polled, wake up another
if !self.received
&& hook
.signal()
.as_any()
.downcast_ref::<SelectSignal>()
.unwrap()
.2
.load(Ordering::SeqCst)
{
wait_lock(&self.receiver.shared.chan).try_wake_receiver_if_pending();
}
}
}
}
let token = self.selections.len();
self.selections.push(Box::new(RecvSelection {
receiver,
token,
signalled: self.signalled.clone(),
hook: None,
mapper,
received: false,
phantom: Default::default(),
}));
self
}
fn wait_inner(mut self, deadline: Option<Instant>) -> Option<T> {
#[cfg(feature = "eventual-fairness")]
{
self.next_poll = self.rng.generate_range(0..self.selections.len());
}
let res = 'outer: loop {
// Init signals
for _ in 0..self.selections.len() {
if let Some(val) = self.selections[self.next_poll].init() {
break 'outer Some(val);
}
self.next_poll = (self.next_poll + 1) % self.selections.len();
}
// Speculatively poll
if let Some(msg) = self.poll() {
break 'outer Some(msg);
}
loop {
if let Some(deadline) = deadline {
if let Some(dur) = deadline.checked_duration_since(Instant::now()) {
thread::park_timeout(dur);
}
} else {
thread::park();
}
if deadline.map(|d| Instant::now() >= d).unwrap_or(false) {
break 'outer self.poll();
}
let token = if let Some(token) = self.signalled.lock().pop_front() {
token
} else {
// Spurious wakeup, park again
continue;
};
// Attempt to receive a message
if let Some(msg) = self.selections[token].poll() {
break 'outer Some(msg);
}
}
};
// Deinit signals
for s in &mut self.selections {
s.deinit();
}
res
}
fn poll(&mut self) -> Option<T> {
for _ in 0..self.selections.len() {
if let Some(val) = self.selections[self.next_poll].poll() {
return Some(val);
}
self.next_poll = (self.next_poll + 1) % self.selections.len();
}
None
}
/// Wait until one of the events associated with this [`Selector`] has completed. If the `eventual-fairness`
/// feature flag is enabled, this method is fair and will handle a random event of those that are ready.
pub fn wait(self) -> T {
self.wait_inner(None).unwrap()
}
/// Wait until one of the events associated with this [`Selector`] has completed or the timeout has expired. If the
/// `eventual-fairness` feature flag is enabled, this method is fair and will handle a random event of those that
/// are ready.
pub fn wait_timeout(self, dur: Duration) -> Result<T, SelectError> {
self.wait_inner(Some(Instant::now() + dur))
.ok_or(SelectError::Timeout)
}
/// Wait until one of the events associated with this [`Selector`] has completed or the deadline has been reached.
/// If the `eventual-fairness` feature flag is enabled, this method is fair and will handle a random event of those
/// that are ready.
pub fn wait_deadline(self, deadline: Instant) -> Result<T, SelectError> {
self.wait_inner(Some(deadline)).ok_or(SelectError::Timeout)
}
}

33
vendor/flume/src/signal.rs vendored Normal file
View File

@ -0,0 +1,33 @@
use std::{thread::{self, Thread}, time::Duration, any::Any};
pub trait Signal: Send + Sync + 'static {
/// Fire the signal, returning whether it is a stream signal. This is because streams do not
/// acquire a message when woken, so signals must be fired until one that does acquire a message
/// is fired, otherwise a wakeup could be missed, leading to a lost message until one is eagerly
/// grabbed by a receiver.
fn fire(&self) -> bool;
fn as_any(&self) -> &(dyn Any + 'static);
fn as_ptr(&self) -> *const ();
}
pub struct SyncSignal(Thread);
impl Default for SyncSignal {
fn default() -> Self {
Self(thread::current())
}
}
impl Signal for SyncSignal {
fn fire(&self) -> bool {
self.0.unpark();
false
}
fn as_any(&self) -> &(dyn Any + 'static) { self }
fn as_ptr(&self) -> *const () { self as *const _ as *const () }
}
impl SyncSignal {
pub fn wait(&self) { thread::park(); }
pub fn wait_timeout(&self, dur: Duration) { thread::park_timeout(dur); }
}

339
vendor/flume/tests/after.rs vendored Normal file
View File

@ -0,0 +1,339 @@
// //! Tests for the after channel flavor.
// #[macro_use]
// extern crate crossbeam_channel;
// extern crate crossbeam_utils;
// extern crate rand;
// use std::sync::atomic::AtomicUsize;
// use std::sync::atomic::Ordering;
// use std::thread;
// use std::time::{Duration, Instant};
// use crossbeam_channel::{after, Select, TryRecvError};
// use crossbeam_utils::thread::scope;
// fn ms(ms: u64) -> Duration {
// Duration::from_millis(ms)
// }
// #[test]
// fn fire() {
// let start = Instant::now();
// let r = after(ms(50));
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// thread::sleep(ms(100));
// let fired = r.try_recv().unwrap();
// assert!(start < fired);
// assert!(fired - start >= ms(50));
// let now = Instant::now();
// assert!(fired < now);
// assert!(now - fired >= ms(50));
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// select! {
// recv(r) -> _ => panic!(),
// default => {}
// }
// select! {
// recv(r) -> _ => panic!(),
// recv(after(ms(200))) -> _ => {}
// }
// }
// #[test]
// fn capacity() {
// const COUNT: usize = 10;
// for i in 0..COUNT {
// let r = after(ms(i as u64));
// assert_eq!(r.capacity(), Some(1));
// }
// }
// #[test]
// fn len_empty_full() {
// let r = after(ms(50));
// assert_eq!(r.len(), 0);
// assert_eq!(r.is_empty(), true);
// assert_eq!(r.is_full(), false);
// thread::sleep(ms(100));
// assert_eq!(r.len(), 1);
// assert_eq!(r.is_empty(), false);
// assert_eq!(r.is_full(), true);
// r.try_recv().unwrap();
// assert_eq!(r.len(), 0);
// assert_eq!(r.is_empty(), true);
// assert_eq!(r.is_full(), false);
// }
// #[test]
// fn try_recv() {
// let r = after(ms(200));
// assert!(r.try_recv().is_err());
// thread::sleep(ms(100));
// assert!(r.try_recv().is_err());
// thread::sleep(ms(200));
// assert!(r.try_recv().is_ok());
// assert!(r.try_recv().is_err());
// thread::sleep(ms(200));
// assert!(r.try_recv().is_err());
// }
// #[test]
// fn recv() {
// let start = Instant::now();
// let r = after(ms(50));
// let fired = r.recv().unwrap();
// assert!(start < fired);
// assert!(fired - start >= ms(50));
// let now = Instant::now();
// assert!(fired < now);
// assert!(now - fired < fired - start);
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// }
// #[test]
// fn recv_timeout() {
// let start = Instant::now();
// let r = after(ms(200));
// assert!(r.recv_timeout(ms(100)).is_err());
// let now = Instant::now();
// assert!(now - start >= ms(100));
// assert!(now - start <= ms(150));
// let fired = r.recv_timeout(ms(200)).unwrap();
// assert!(fired - start >= ms(200));
// assert!(fired - start <= ms(250));
// assert!(r.recv_timeout(ms(200)).is_err());
// let now = Instant::now();
// assert!(now - start >= ms(400));
// assert!(now - start <= ms(450));
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// }
// #[test]
// fn recv_two() {
// let r1 = after(ms(50));
// let r2 = after(ms(50));
// scope(|scope| {
// scope.spawn(|_| {
// select! {
// recv(r1) -> _ => {}
// recv(r2) -> _ => {}
// }
// });
// scope.spawn(|_| {
// select! {
// recv(r1) -> _ => {}
// recv(r2) -> _ => {}
// }
// });
// })
// .unwrap();
// }
// #[test]
// fn recv_race() {
// select! {
// recv(after(ms(50))) -> _ => {}
// recv(after(ms(100))) -> _ => panic!(),
// }
// select! {
// recv(after(ms(100))) -> _ => panic!(),
// recv(after(ms(50))) -> _ => {}
// }
// }
// #[test]
// fn stress_default() {
// const COUNT: usize = 10;
// for _ in 0..COUNT {
// select! {
// recv(after(ms(0))) -> _ => {}
// default => panic!(),
// }
// }
// for _ in 0..COUNT {
// select! {
// recv(after(ms(100))) -> _ => panic!(),
// default => {}
// }
// }
// }
// #[test]
// fn select() {
// const THREADS: usize = 4;
// const COUNT: usize = 1000;
// const TIMEOUT_MS: u64 = 100;
// let v = (0..COUNT)
// .map(|i| after(ms(i as u64 / TIMEOUT_MS / 2)))
// .collect::<Vec<_>>();
// let hits = AtomicUsize::new(0);
// scope(|scope| {
// for _ in 0..THREADS {
// scope.spawn(|_| {
// let v: Vec<&_> = v.iter().collect();
// loop {
// let timeout = after(ms(TIMEOUT_MS));
// let mut sel = Select::new();
// for r in &v {
// sel.recv(r);
// }
// let oper_timeout = sel.recv(&timeout);
// let oper = sel.select();
// match oper.index() {
// i if i == oper_timeout => {
// oper.recv(&timeout).unwrap();
// break;
// }
// i => {
// oper.recv(&v[i]).unwrap();
// hits.fetch_add(1, Ordering::SeqCst);
// }
// }
// }
// });
// }
// })
// .unwrap();
// assert_eq!(hits.load(Ordering::SeqCst), COUNT);
// }
// #[test]
// fn ready() {
// const THREADS: usize = 4;
// const COUNT: usize = 1000;
// const TIMEOUT_MS: u64 = 100;
// let v = (0..COUNT)
// .map(|i| after(ms(i as u64 / TIMEOUT_MS / 2)))
// .collect::<Vec<_>>();
// let hits = AtomicUsize::new(0);
// scope(|scope| {
// for _ in 0..THREADS {
// scope.spawn(|_| {
// let v: Vec<&_> = v.iter().collect();
// loop {
// let timeout = after(ms(TIMEOUT_MS));
// let mut sel = Select::new();
// for r in &v {
// sel.recv(r);
// }
// let oper_timeout = sel.recv(&timeout);
// loop {
// let i = sel.ready();
// if i == oper_timeout {
// timeout.try_recv().unwrap();
// return;
// } else if v[i].try_recv().is_ok() {
// hits.fetch_add(1, Ordering::SeqCst);
// break;
// }
// }
// }
// });
// }
// })
// .unwrap();
// assert_eq!(hits.load(Ordering::SeqCst), COUNT);
// }
// #[test]
// fn stress_clone() {
// const RUNS: usize = 1000;
// const THREADS: usize = 10;
// const COUNT: usize = 50;
// for i in 0..RUNS {
// let r = after(ms(i as u64));
// scope(|scope| {
// for _ in 0..THREADS {
// scope.spawn(|_| {
// let r = r.clone();
// let _ = r.try_recv();
// for _ in 0..COUNT {
// drop(r.clone());
// thread::yield_now();
// }
// });
// }
// })
// .unwrap();
// }
// }
// #[test]
// fn fairness() {
// const COUNT: usize = 1000;
// for &dur in &[0, 1] {
// let mut hits = [0usize; 2];
// for _ in 0..COUNT {
// select! {
// recv(after(ms(dur))) -> _ => hits[0] += 1,
// recv(after(ms(dur))) -> _ => hits[1] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// }
// #[test]
// fn fairness_duplicates() {
// const COUNT: usize = 1000;
// for &dur in &[0, 1] {
// let mut hits = [0usize; 5];
// for _ in 0..COUNT {
// let r = after(ms(dur));
// select! {
// recv(r) -> _ => hits[0] += 1,
// recv(r) -> _ => hits[1] += 1,
// recv(r) -> _ => hits[2] += 1,
// recv(r) -> _ => hits[3] += 1,
// recv(r) -> _ => hits[4] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// }

657
vendor/flume/tests/array.rs vendored Normal file
View File

@ -0,0 +1,657 @@
//! Tests for the array channel flavor.
extern crate crossbeam_utils;
extern crate rand;
use std::any::Any;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
use flume::{bounded, Receiver};
use flume::{RecvError, RecvTimeoutError, TryRecvError};
use flume::{SendError, SendTimeoutError, TrySendError};
use crossbeam_utils::thread::scope;
use rand::{thread_rng, Rng};
fn ms(ms: u64) -> Duration {
Duration::from_millis(ms)
}
#[test]
fn smoke() {
let (s, r) = bounded(1);
s.send(7).unwrap();
assert_eq!(r.try_recv(), Ok(7));
s.send(8).unwrap();
assert_eq!(r.recv(), Ok(8));
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
}
#[test]
fn capacity() {
for i in 1..10 {
let (s, r) = bounded::<()>(i);
assert_eq!(s.capacity(), Some(i));
assert_eq!(r.capacity(), Some(i));
}
}
#[test]
fn len_empty_full() {
let (s, r) = bounded(2);
assert_eq!(s.len(), 0);
assert_eq!(s.is_empty(), true);
assert_eq!(s.is_full(), false);
assert_eq!(r.len(), 0);
assert_eq!(r.is_empty(), true);
assert_eq!(r.is_full(), false);
s.send(()).unwrap();
assert_eq!(s.len(), 1);
assert_eq!(s.is_empty(), false);
assert_eq!(s.is_full(), false);
assert_eq!(r.len(), 1);
assert_eq!(r.is_empty(), false);
assert_eq!(r.is_full(), false);
s.send(()).unwrap();
assert_eq!(s.len(), 2);
assert_eq!(s.is_empty(), false);
assert_eq!(s.is_full(), true);
assert_eq!(r.len(), 2);
assert_eq!(r.is_empty(), false);
assert_eq!(r.is_full(), true);
r.recv().unwrap();
assert_eq!(s.len(), 1);
assert_eq!(s.is_empty(), false);
assert_eq!(s.is_full(), false);
assert_eq!(r.len(), 1);
assert_eq!(r.is_empty(), false);
assert_eq!(r.is_full(), false);
}
#[test]
fn try_recv() {
let (s, r) = bounded(100);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
thread::sleep(ms(1500));
assert_eq!(r.try_recv(), Ok(7));
thread::sleep(ms(500));
assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
s.send(7).unwrap();
});
})
.unwrap();
}
#[test]
fn recv() {
let (s, r) = bounded(100);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.recv(), Ok(7));
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(8));
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(9));
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
s.send(7).unwrap();
s.send(8).unwrap();
s.send(9).unwrap();
});
})
.unwrap();
}
#[test]
fn recv_timeout() {
let (s, r) = bounded::<i32>(100);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
assert_eq!(r.recv_timeout(ms(1000)), Ok(7));
assert_eq!(
r.recv_timeout(ms(1000)),
Err(RecvTimeoutError::Disconnected)
);
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
s.send(7).unwrap();
});
})
.unwrap();
}
#[test]
fn try_send() {
let (s, r) = bounded(1);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(s.try_send(1), Ok(()));
assert_eq!(s.try_send(2), Err(TrySendError::Full(2)));
thread::sleep(ms(1500));
assert_eq!(s.try_send(3), Ok(()));
thread::sleep(ms(500));
assert_eq!(s.try_send(4), Err(TrySendError::Disconnected(4)));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
assert_eq!(r.try_recv(), Ok(1));
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
assert_eq!(r.recv(), Ok(3));
});
})
.unwrap();
}
#[test]
fn send() {
let (s, r) = bounded(1);
scope(|scope| {
scope.spawn(|_| {
s.send(7).unwrap();
thread::sleep(ms(1000));
s.send(8).unwrap();
thread::sleep(ms(1000));
s.send(9).unwrap();
thread::sleep(ms(1000));
s.send(10).unwrap();
});
scope.spawn(|_| {
thread::sleep(ms(1500));
assert_eq!(r.recv(), Ok(7));
assert_eq!(r.recv(), Ok(8));
assert_eq!(r.recv(), Ok(9));
});
})
.unwrap();
}
#[test]
fn send_timeout() {
let (s, r) = bounded(2);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(s.send_timeout(1, ms(1000)), Ok(()));
assert_eq!(s.send_timeout(2, ms(1000)), Ok(()));
assert_eq!(
s.send_timeout(3, ms(500)),
Err(SendTimeoutError::Timeout(3))
);
thread::sleep(ms(1000));
assert_eq!(s.send_timeout(4, ms(1000)), Ok(()));
thread::sleep(ms(1000));
assert_eq!(s.send(5), Err(SendError(5)));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(1));
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(2));
assert_eq!(r.recv(), Ok(4));
});
})
.unwrap();
}
#[test]
fn send_after_disconnect() {
let (s, r) = bounded(100);
s.send(1).unwrap();
s.send(2).unwrap();
s.send(3).unwrap();
drop(r);
assert_eq!(s.send(4), Err(SendError(4)));
assert_eq!(s.try_send(5), Err(TrySendError::Disconnected(5)));
assert_eq!(
s.send_timeout(6, ms(500)),
Err(SendTimeoutError::Disconnected(6))
);
}
#[test]
fn recv_after_disconnect() {
let (s, r) = bounded(100);
s.send(1).unwrap();
s.send(2).unwrap();
s.send(3).unwrap();
drop(s);
assert_eq!(r.recv(), Ok(1));
assert_eq!(r.recv(), Ok(2));
assert_eq!(r.recv(), Ok(3));
assert!(r.recv().is_err());
}
#[test]
fn len() {
const COUNT: usize = 25_000;
const CAP: usize = 1000;
let (s, r) = bounded(CAP);
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
for _ in 0..CAP / 10 {
for i in 0..50 {
s.send(i).unwrap();
assert_eq!(s.len(), i + 1);
}
for i in 0..50 {
r.recv().unwrap();
assert_eq!(r.len(), 50 - i - 1);
}
}
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
for i in 0..CAP {
s.send(i).unwrap();
assert_eq!(s.len(), i + 1);
}
for _ in 0..CAP {
r.recv().unwrap();
}
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
scope(|scope| {
scope.spawn(|_| {
for i in 0..COUNT {
assert_eq!(r.recv(), Ok(i));
let len = r.len();
assert!(len <= CAP);
}
});
scope.spawn(|_| {
for i in 0..COUNT {
s.send(i).unwrap();
let len = s.len();
assert!(len <= CAP);
}
});
})
.unwrap();
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
}
#[test]
fn disconnect_wakes_sender() {
let (s, r) = bounded(1);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(s.send(()), Ok(()));
assert_eq!(s.send(()), Err(SendError(())));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
drop(r);
});
})
.unwrap();
}
#[test]
fn disconnect_wakes_receiver() {
let (s, r) = bounded::<()>(1);
scope(|scope| {
scope.spawn(move |_| {
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
drop(s);
});
})
.unwrap();
}
#[test]
fn spsc() {
const COUNT: usize = 100_000;
let (s, r) = bounded(3);
scope(|scope| {
scope.spawn(move |_| {
for i in 0..COUNT {
assert_eq!(r.recv(), Ok(i));
}
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
for i in 0..COUNT {
s.send(i).unwrap();
}
});
})
.unwrap();
}
#[test]
fn mpmc() {
const COUNT: usize = 25_000;
const THREADS: usize = 4;
let (s, r) = bounded::<usize>(3);
let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();
scope(|scope| {
for _ in 0..THREADS {
scope.spawn(|_| {
for _ in 0..COUNT {
let n = r.recv().unwrap();
v[n].fetch_add(1, Ordering::SeqCst);
}
});
}
for _ in 0..THREADS {
scope.spawn(|_| {
for i in 0..COUNT {
s.send(i).unwrap();
}
});
}
})
.unwrap();
for c in v {
assert_eq!(c.load(Ordering::SeqCst), THREADS);
}
}
#[test]
fn stress_oneshot() {
const COUNT: usize = 10_000;
for _ in 0..COUNT {
let (s, r) = bounded(1);
scope(|scope| {
scope.spawn(|_| r.recv().unwrap());
scope.spawn(|_| s.send(0).unwrap());
})
.unwrap();
}
}
#[test]
fn stress_iter() {
const COUNT: usize = 100_000;
let (request_s, request_r) = bounded(1);
let (response_s, response_r) = bounded(1);
scope(|scope| {
scope.spawn(move |_| {
let mut count = 0;
loop {
for x in response_r.try_iter() {
count += x;
if count == COUNT {
return;
}
}
request_s.send(()).unwrap();
}
});
for _ in request_r.iter() {
if response_s.send(1).is_err() {
break;
}
}
})
.unwrap();
}
#[test]
fn stress_timeout_two_threads() {
const COUNT: usize = 100;
let (s, r) = bounded(2);
scope(|scope| {
scope.spawn(|_| {
for i in 0..COUNT {
if i % 2 == 0 {
thread::sleep(ms(50));
}
loop {
if let Ok(()) = s.send_timeout(i, ms(10)) {
break;
}
}
}
});
scope.spawn(|_| {
for i in 0..COUNT {
if i % 2 == 0 {
thread::sleep(ms(50));
}
loop {
if let Ok(x) = r.recv_timeout(ms(10)) {
assert_eq!(x, i);
break;
}
}
}
});
})
.unwrap();
}
#[test]
fn drops() {
const RUNS: usize = 100;
static DROPS: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, PartialEq)]
struct DropCounter;
impl Drop for DropCounter {
fn drop(&mut self) {
DROPS.fetch_add(1, Ordering::SeqCst);
}
}
let mut rng = thread_rng();
for _ in 0..RUNS {
let steps = rng.gen_range(0..10_000);
let additional = rng.gen_range(0..50);
DROPS.store(0, Ordering::SeqCst);
let (s, r) = bounded::<DropCounter>(50);
scope(|scope| {
scope.spawn(|_| {
for _ in 0..steps {
r.recv().unwrap();
}
});
scope.spawn(|_| {
for _ in 0..steps {
s.send(DropCounter).unwrap();
}
});
})
.unwrap();
for _ in 0..additional {
s.send(DropCounter).unwrap();
}
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
drop(s);
drop(r);
assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional);
}
}
#[test]
fn linearizable() {
const COUNT: usize = 25_000;
const THREADS: usize = 4;
let (s, r) = bounded(THREADS);
scope(|scope| {
for _ in 0..THREADS {
scope.spawn(|_| {
for _ in 0..COUNT {
s.send(0).unwrap();
r.try_recv().unwrap();
}
});
}
})
.unwrap();
}
// #[test]
// fn fairness() {
// const COUNT: usize = 10_000;
// let (s1, r1) = bounded::<()>(COUNT);
// let (s2, r2) = bounded::<()>(COUNT);
// for _ in 0..COUNT {
// s1.send(()).unwrap();
// s2.send(()).unwrap();
// }
// let mut hits = [0usize; 2];
// for _ in 0..COUNT {
// select! {
// recv(r1) -> _ => hits[0] += 1,
// recv(r2) -> _ => hits[1] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// #[test]
// fn fairness_duplicates() {
// const COUNT: usize = 10_000;
// let (s, r) = bounded::<()>(COUNT);
// for _ in 0..COUNT {
// s.send(()).unwrap();
// }
// let mut hits = [0usize; 5];
// for _ in 0..COUNT {
// select! {
// recv(r) -> _ => hits[0] += 1,
// recv(r) -> _ => hits[1] += 1,
// recv(r) -> _ => hits[2] += 1,
// recv(r) -> _ => hits[3] += 1,
// recv(r) -> _ => hits[4] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// #[test]
// fn recv_in_send() {
// let (s, _r) = bounded(1);
// s.send(()).unwrap();
// #[allow(unreachable_code)]
// {
// select! {
// send(s, panic!()) -> _ => panic!(),
// default => {}
// }
// }
// let (s, r) = bounded(2);
// s.send(()).unwrap();
// select! {
// send(s, assert_eq!(r.recv(), Ok(()))) -> _ => {}
// }
// }
#[test]
fn channel_through_channel() {
const COUNT: usize = 1000;
type T = Box<dyn Any + Send>;
let (s, r) = bounded::<T>(1);
scope(|scope| {
scope.spawn(move |_| {
let mut s = s;
for _ in 0..COUNT {
let (new_s, new_r) = bounded(1);
let new_r: T = Box::new(Some(new_r));
s.send(new_r).unwrap();
s = new_s;
}
});
scope.spawn(move |_| {
let mut r = r;
for _ in 0..COUNT {
r = r
.recv()
.unwrap()
.downcast_mut::<Option<Receiver<T>>>()
.unwrap()
.take()
.unwrap()
}
});
})
.unwrap();
}

276
vendor/flume/tests/async.rs vendored Normal file
View File

@ -0,0 +1,276 @@
#[cfg(feature = "async")]
use {
flume::*,
futures::{stream::FuturesUnordered, StreamExt, TryFutureExt, Future},
futures::task::{Context, Waker, Poll},
async_std::prelude::FutureExt,
std::{time::Duration, sync::{atomic::{AtomicUsize, Ordering}, Arc}},
};
#[cfg(feature = "async")]
#[test]
fn r#async_recv() {
let (tx, rx) = unbounded();
let t = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(250));
tx.send(42u32).unwrap();
});
async_std::task::block_on(async {
assert_eq!(rx.recv_async().await.unwrap(), 42);
});
t.join().unwrap();
}
#[cfg(feature = "async")]
#[test]
fn r#async_send() {
let (tx, rx) = bounded(1);
let t = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(250));
assert_eq!(rx.recv(), Ok(42));
});
async_std::task::block_on(async {
tx.send_async(42u32).await.unwrap();
});
t.join().unwrap();
}
#[cfg(feature = "async")]
#[test]
fn r#async_recv_disconnect() {
let (tx, rx) = bounded::<i32>(0);
let t = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(250));
drop(tx)
});
async_std::task::block_on(async {
assert_eq!(rx.recv_async().await, Err(RecvError::Disconnected));
});
t.join().unwrap();
}
#[cfg(feature = "async")]
#[test]
fn r#async_send_disconnect() {
let (tx, rx) = bounded(0);
let t = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(250));
drop(rx)
});
async_std::task::block_on(async {
assert_eq!(tx.send_async(42u32).await, Err(SendError(42)));
});
t.join().unwrap();
}
#[cfg(feature = "async")]
#[test]
fn r#async_recv_drop_recv() {
let (tx, rx) = bounded::<i32>(10);
let recv_fut = rx.recv_async();
async_std::task::block_on(async {
let res = async_std::future::timeout(std::time::Duration::from_millis(500), rx.recv_async()).await;
assert!(res.is_err());
});
let rx2 = rx.clone();
let t = std::thread::spawn(move || {
async_std::task::block_on(async {
rx2.recv_async().await
})
});
std::thread::sleep(std::time::Duration::from_millis(500));
tx.send(42).unwrap();
drop(recv_fut);
assert_eq!(t.join().unwrap(), Ok(42))
}
#[cfg(feature = "async")]
#[async_std::test]
async fn r#async_send_1_million_no_drop_or_reorder() {
#[derive(Debug)]
enum Message {
Increment {
old: u64,
},
ReturnCount,
}
let (tx, rx) = unbounded();
let t = async_std::task::spawn(async move {
let mut count = 0u64;
while let Ok(Message::Increment { old }) = rx.recv_async().await {
assert_eq!(old, count);
count += 1;
}
count
});
for next in 0..1_000_000 {
tx.send(Message::Increment { old: next }).unwrap();
}
tx.send(Message::ReturnCount).unwrap();
let count = t.await;
assert_eq!(count, 1_000_000)
}
#[cfg(feature = "async")]
#[async_std::test]
async fn parallel_async_receivers() {
let (tx, rx) = flume::unbounded();
let send_fut = async move {
let n_sends: usize = 100000;
for _ in 0..n_sends {
tx.send_async(()).await.unwrap();
}
};
async_std::task::spawn(
send_fut
.timeout(Duration::from_secs(5))
.map_err(|_| panic!("Send timed out!"))
);
let mut futures_unordered = (0..250)
.map(|_| async {
while let Ok(()) = rx.recv_async().await
/* rx.recv() is OK */
{}
})
.collect::<FuturesUnordered<_>>();
let recv_fut = async {
while futures_unordered.next().await.is_some() {}
};
recv_fut
.timeout(Duration::from_secs(5))
.map_err(|_| panic!("Receive timed out!"))
.await
.unwrap();
println!("recv end");
}
#[cfg(feature = "async")]
#[test]
fn change_waker() {
let (tx, rx) = flume::bounded(1);
tx.send(()).unwrap();
struct DebugWaker(Arc<AtomicUsize>, Waker);
impl DebugWaker {
fn new() -> Self {
let woken = Arc::new(AtomicUsize::new(0));
let woken_cloned = woken.clone();
let waker = waker_fn::waker_fn(move || {
woken.fetch_add(1, Ordering::SeqCst);
});
DebugWaker(woken_cloned, waker)
}
fn woken(&self) -> usize {
self.0.load(Ordering::SeqCst)
}
fn ctx(&self) -> Context {
Context::from_waker(&self.1)
}
}
// Check that the waker is correctly updated when sending tasks change their wakers
{
let send_fut = tx.send_async(());
futures::pin_mut!(send_fut);
let (waker1, waker2) = (DebugWaker::new(), DebugWaker::new());
// Set the waker to waker1
assert_eq!(send_fut.as_mut().poll(&mut waker1.ctx()), Poll::Pending);
// Change the waker to waker2
assert_eq!(send_fut.poll(&mut waker2.ctx()), Poll::Pending);
// Wake the future
rx.recv().unwrap();
// Check that waker2 was woken and waker1 was not
assert_eq!(waker1.woken(), 0);
assert_eq!(waker2.woken(), 1);
}
// Check that the waker is correctly updated when receiving tasks change their wakers
{
rx.recv().unwrap();
let recv_fut = rx.recv_async();
futures::pin_mut!(recv_fut);
let (waker1, waker2) = (DebugWaker::new(), DebugWaker::new());
// Set the waker to waker1
assert_eq!(recv_fut.as_mut().poll(&mut waker1.ctx()), Poll::Pending);
// Change the waker to waker2
assert_eq!(recv_fut.poll(&mut waker2.ctx()), Poll::Pending);
// Wake the future
tx.send(()).unwrap();
// Check that waker2 was woken and waker1 was not
assert_eq!(waker1.woken(), 0);
assert_eq!(waker2.woken(), 1);
}
}
#[cfg(feature = "async")]
#[test]
fn spsc_single_threaded_value_ordering() {
async fn test() {
let (tx, rx) = flume::bounded(4);
tokio::select! {
_ = producer(tx) => {},
_ = consumer(rx) => {},
}
}
async fn producer(tx: flume::Sender<usize>) {
for i in 0..100 {
tx.send_async(i).await.unwrap();
}
}
async fn consumer(rx: flume::Receiver<usize>) {
let mut expected = 0;
while let Ok(value) = rx.recv_async().await {
assert_eq!(value, expected);
expected += 1;
}
}
let rt = tokio::runtime::Builder::new_current_thread().build().unwrap();
rt.block_on(test());
}

428
vendor/flume/tests/basic.rs vendored Normal file
View File

@ -0,0 +1,428 @@
use std::time::{Instant, Duration};
use flume::*;
#[test]
fn send_recv() {
let (tx, rx) = unbounded();
for i in 0..1000 { tx.send(i).unwrap(); }
for i in 0..1000 { assert_eq!(rx.try_recv().unwrap(), i); }
assert!(rx.try_recv().is_err());
}
#[test]
fn iter() {
let (tx, rx) = unbounded();
for i in 0..1000 { tx.send(i).unwrap(); }
drop(tx);
assert_eq!(rx.iter().sum::<u32>(), (0..1000).sum());
}
#[test]
fn try_iter() {
let (tx, rx) = unbounded();
for i in 0..1000 { tx.send(i).unwrap(); }
assert_eq!(rx.try_iter().sum::<u32>(), (0..1000).sum());
}
#[test]
fn iter_threaded() {
let (tx, rx) = unbounded();
for i in 0..1000 {
let tx = tx.clone();
std::thread::spawn(move || tx.send(i).unwrap());
}
drop(tx);
assert_eq!(rx.iter().sum::<u32>(), (0..1000).sum());
}
#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41
#[test]
fn send_timeout() {
let dur = Duration::from_millis(350);
let max_error = Duration::from_millis(5);
let dur_min = dur.checked_sub(max_error).unwrap();
let dur_max = dur.checked_add(max_error).unwrap();
let (tx, rx) = bounded(1);
assert!(tx.send_timeout(42, dur).is_ok());
let then = Instant::now();
assert!(tx.send_timeout(43, dur).is_err());
let now = Instant::now();
let this = now.duration_since(then);
if !(dur_min < this && this < dur_max) {
panic!("timeout exceeded: {:?}", this);
}
assert_eq!(rx.drain().count(), 1);
drop(rx);
assert!(tx.send_timeout(42, Duration::from_millis(350)).is_err());
}
#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41
#[test]
fn recv_timeout() {
let dur = Duration::from_millis(350);
let max_error = Duration::from_millis(5);
let dur_min = dur.checked_sub(max_error).unwrap();
let dur_max = dur.checked_add(max_error).unwrap();
let (tx, rx) = unbounded();
let then = Instant::now();
assert!(rx.recv_timeout(dur).is_err());
let now = Instant::now();
let this = now.duration_since(then);
if !(dur_min < this && this < dur_max) {
panic!("timeout exceeded: {:?}", this);
}
tx.send(42).unwrap();
assert_eq!(rx.recv_timeout(dur), Ok(42));
assert!(Instant::now().duration_since(now) < max_error);
}
#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41
#[test]
fn recv_deadline() {
let dur = Duration::from_millis(350);
let max_error = Duration::from_millis(5);
let dur_min = dur.checked_sub(max_error).unwrap();
let dur_max = dur.checked_add(max_error).unwrap();
let (tx, rx) = unbounded();
let then = Instant::now();
assert!(rx.recv_deadline(then.checked_add(dur).unwrap()).is_err());
let now = Instant::now();
let this = now.duration_since(then);
if !(dur_min < this && this < dur_max) {
panic!("timeout exceeded: {:?}", this);
}
tx.send(42).unwrap();
assert_eq!(rx.recv_deadline(now.checked_add(dur).unwrap()), Ok(42));
assert!(Instant::now().duration_since(now) < max_error);
}
#[test]
fn recv_timeout_missed_send() {
let (tx, rx) = bounded(10);
assert!(rx.recv_timeout(Duration::from_millis(100)).is_err());
tx.send(42).unwrap();
assert_eq!(rx.recv(), Ok(42));
}
#[test]
fn disconnect_tx() {
let (tx, rx) = unbounded::<()>();
drop(tx);
assert!(rx.recv().is_err());
}
#[test]
fn disconnect_rx() {
let (tx, rx) = unbounded();
drop(rx);
assert!(tx.send(0).is_err());
}
#[test]
fn drain() {
let (tx, rx) = unbounded();
for i in 0..100 {
tx.send(i).unwrap();
}
assert_eq!(rx.drain().sum::<u32>(), (0..100).sum());
for i in 0..100 {
tx.send(i).unwrap();
}
for i in 0..100 {
tx.send(i).unwrap();
}
rx.recv().unwrap();
(1u32..100).chain(0..100).zip(rx).for_each(|(l, r)| assert_eq!(l, r));
}
#[test]
fn try_send() {
let (tx, rx) = bounded(5);
for i in 0..5 {
tx.try_send(i).unwrap();
}
assert!(tx.try_send(42).is_err());
assert_eq!(rx.recv(), Ok(0));
assert_eq!(tx.try_send(42), Ok(()));
assert_eq!(rx.recv(), Ok(1));
drop(rx);
assert!(tx.try_send(42).is_err());
}
#[test]
fn send_bounded() {
let (tx, rx) = bounded(5);
for _ in 0..5 {
tx.send(42).unwrap();
}
let _ = rx.recv().unwrap();
tx.send(42).unwrap();
assert!(tx.try_send(42).is_err());
rx.drain();
let mut ts = Vec::new();
for _ in 0..100 {
let tx = tx.clone();
ts.push(std::thread::spawn(move || {
for i in 0..10000 {
tx.send(i).unwrap();
}
}));
}
drop(tx);
assert_eq!(rx.iter().sum::<u64>(), (0..10000).sum::<u64>() * 100);
for t in ts {
t.join().unwrap();
}
assert!(rx.recv().is_err());
}
#[test]
fn rendezvous() {
let (tx, rx) = bounded(0);
for i in 0..5 {
let tx = tx.clone();
let t = std::thread::spawn(move || {
assert!(tx.try_send(()).is_err());
let then = Instant::now();
tx.send(()).unwrap();
let now = Instant::now();
assert!(now.duration_since(then) > Duration::from_millis(100), "iter = {}", i);
});
std::thread::sleep(Duration::from_millis(1000));
rx.recv().unwrap();
t.join().unwrap();
}
}
#[test]
fn hydra() {
let thread_num = 32;
let msg_num = 1000;
let (main_tx, main_rx) = unbounded::<()>();
let mut txs = Vec::new();
for _ in 0..thread_num {
let main_tx = main_tx.clone();
let (tx, rx) = unbounded();
txs.push(tx);
std::thread::spawn(move || {
for msg in rx.iter() {
main_tx.send(msg).unwrap();
}
});
}
drop(main_tx);
for _ in 0..10 {
for tx in &txs {
for _ in 0..msg_num {
tx.send(Default::default()).unwrap();
}
}
for _ in 0..thread_num {
for _ in 0..msg_num {
main_rx.recv().unwrap();
}
}
}
drop(txs);
assert!(main_rx.recv().is_err());
}
#[test]
fn robin() {
let thread_num = 32;
let msg_num = 10;
let (mut main_tx, main_rx) = bounded::<()>(1);
for _ in 0..thread_num {
let (mut tx, rx) = bounded(100);
std::mem::swap(&mut tx, &mut main_tx);
std::thread::spawn(move || {
for msg in rx.iter() {
tx.send(msg).unwrap();
}
});
}
for _ in 0..10 {
let main_tx = main_tx.clone();
std::thread::spawn(move || {
for _ in 0..msg_num {
main_tx.send(Default::default()).unwrap();
}
});
for _ in 0..msg_num {
main_rx.recv().unwrap();
}
}
}
#[cfg(feature = "select")]
#[test]
fn select_general() {
#[derive(Debug, PartialEq)]
struct Foo(usize);
let (tx0, rx0) = bounded(1);
let (tx1, rx1) = unbounded();
for (i, t) in vec![tx0.clone(), tx1].into_iter().enumerate() {
std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(250));
let _ = t.send(Foo(i));
});
}
let x = Selector::new()
.recv(&rx0, |x| x)
.recv(&rx1, |x| x)
.wait()
.unwrap();
if x == Foo(0) {
assert!(rx1.recv().unwrap() == Foo(1));
} else {
assert!(rx0.recv().unwrap() == Foo(0));
}
tx0.send(Foo(42)).unwrap();
let t = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(100));
assert_eq!(rx0.recv().unwrap(), Foo(42));
assert_eq!(rx0.recv().unwrap(), Foo(43));
});
Selector::new()
.send(&tx0, Foo(43), |x| x)
.wait()
.unwrap();
t.join().unwrap();
}
struct MessageWithoutDebug(u32);
#[test]
// This is a 'does it build' test, to make sure that the error types can turn
// into a std::error::Error without requiring the payload (which is not used
// there) to impl Debug.
fn std_error_without_debug() {
let (tx, rx) = unbounded::<MessageWithoutDebug>();
match tx.send(MessageWithoutDebug(1)) {
Ok(_) => {}
Err(e) => {
let _std_err: &dyn std::error::Error = &e;
}
}
match rx.recv() {
Ok(_) => {}
Err(e) => {
let _std_err: &dyn std::error::Error = &e;
}
}
match tx.try_send(MessageWithoutDebug(2)) {
Ok(_) => {}
Err(e) => {
let _std_err: &dyn std::error::Error = &e;
}
}
match rx.try_recv() {
Ok(_) => {}
Err(e) => {
let _std_err: &dyn std::error::Error = &e;
}
}
match tx.send_timeout(MessageWithoutDebug(3), Duration::from_secs(1000000)) {
Ok(_) => {}
Err(e) => {
let _std_err: &dyn std::error::Error = &e;
}
}
match rx.recv_timeout(Duration::from_secs(10000000)) {
Ok(_) => {}
Err(e) => {
let _std_err: &dyn std::error::Error = &e;
}
}
}
#[test]
fn weak_close() {
let (tx, rx) = unbounded::<()>();
let weak = tx.downgrade();
drop(tx);
assert!(weak.upgrade().is_none());
assert!(rx.is_disconnected());
assert!(rx.try_recv().is_err());
}
#[test]
fn weak_upgrade() {
let (tx, rx) = unbounded();
let weak = tx.downgrade();
let tx2 = weak.upgrade().unwrap();
drop(tx);
assert!(!rx.is_disconnected());
tx2.send(()).unwrap();
assert!(rx.try_recv().is_ok());
}

View File

@ -0,0 +1,57 @@
#[test]
fn same_sender() {
let (tx1, _rx) = flume::unbounded::<()>();
let tx2 = tx1.clone();
assert!(tx1.same_channel(&tx2));
let (tx3, _rx) = flume::unbounded::<()>();
assert!(!tx1.same_channel(&tx3));
assert!(!tx2.same_channel(&tx3));
}
#[test]
fn same_receiver() {
let (_tx, rx1) = flume::unbounded::<()>();
let rx2 = rx1.clone();
assert!(rx1.same_channel(&rx2));
let (_tx, rx3) = flume::unbounded::<()>();
assert!(!rx1.same_channel(&rx3));
assert!(!rx2.same_channel(&rx3));
}
#[cfg(feature = "async")]
#[test]
fn same_send_sink() {
let (tx1, _rx) = flume::unbounded::<()>();
let tx1 = tx1.into_sink();
let tx2 = tx1.clone();
assert!(tx1.same_channel(&tx2));
let (tx3, _rx) = flume::unbounded::<()>();
let tx3 = tx3.into_sink();
assert!(!tx1.same_channel(&tx3));
assert!(!tx2.same_channel(&tx3));
}
#[cfg(feature = "async")]
#[test]
fn same_recv_stream() {
let (_tx, rx1) = flume::unbounded::<()>();
let rx1 = rx1.into_stream();
let rx2 = rx1.clone();
assert!(rx1.same_channel(&rx2));
let (_tx, rx3) = flume::unbounded::<()>();
let rx3 = rx3.into_stream();
assert!(!rx1.same_channel(&rx3));
assert!(!rx2.same_channel(&rx3));
}

1445
vendor/flume/tests/golang.rs vendored Normal file

File diff suppressed because it is too large Load Diff

112
vendor/flume/tests/iter.rs vendored Normal file
View File

@ -0,0 +1,112 @@
//! Tests for iteration over receivers.
extern crate crossbeam_utils;
use flume::unbounded;
use crossbeam_utils::thread::scope;
#[test]
fn nested_recv_iter() {
let (s, r) = unbounded::<i32>();
let (total_s, total_r) = unbounded::<i32>();
scope(|scope| {
scope.spawn(move |_| {
let mut acc = 0;
for x in r.iter() {
acc += x;
}
total_s.send(acc).unwrap();
});
s.send(3).unwrap();
s.send(1).unwrap();
s.send(2).unwrap();
drop(s);
assert_eq!(total_r.recv().unwrap(), 6);
})
.unwrap();
}
#[test]
fn recv_iter_break() {
let (s, r) = unbounded::<i32>();
let (count_s, count_r) = unbounded();
scope(|scope| {
scope.spawn(move |_| {
let mut count = 0;
for x in r.iter() {
if count >= 3 {
break;
} else {
count += x;
}
}
count_s.send(count).unwrap();
});
s.send(2).unwrap();
s.send(2).unwrap();
s.send(2).unwrap();
let _ = s.send(2);
drop(s);
assert_eq!(count_r.recv().unwrap(), 4);
})
.unwrap();
}
#[test]
fn recv_try_iter() {
let (request_s, request_r) = unbounded();
let (response_s, response_r) = unbounded();
scope(|scope| {
scope.spawn(move |_| {
let mut count = 0;
loop {
for x in response_r.try_iter() {
count += x;
if count == 6 {
return;
}
}
request_s.send(()).unwrap();
}
});
for _ in request_r.iter() {
if response_s.send(2).is_err() {
break;
}
}
})
.unwrap();
}
#[test]
fn recv_into_iter_owned() {
let mut iter = {
let (s, r) = unbounded::<i32>();
s.send(1).unwrap();
s.send(2).unwrap();
r.into_iter()
};
assert_eq!(iter.next().unwrap(), 1);
assert_eq!(iter.next().unwrap(), 2);
assert_eq!(iter.next().is_none(), true);
}
#[test]
fn recv_into_iter_borrowed() {
let (s, r) = unbounded::<i32>();
s.send(1).unwrap();
s.send(2).unwrap();
drop(s);
let mut iter = (&r).into_iter();
assert_eq!(iter.next().unwrap(), 1);
assert_eq!(iter.next().unwrap(), 2);
assert_eq!(iter.next().is_none(), true);
}

536
vendor/flume/tests/list.rs vendored Normal file
View File

@ -0,0 +1,536 @@
//! Tests for the list channel flavor.
extern crate crossbeam_utils;
extern crate rand;
use std::any::Any;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
use flume::{unbounded, Receiver};
use flume::{RecvError, RecvTimeoutError, TryRecvError};
use flume::{SendError, SendTimeoutError, TrySendError};
use crossbeam_utils::thread::scope;
use rand::{thread_rng, Rng};
fn ms(ms: u64) -> Duration {
Duration::from_millis(ms)
}
#[test]
fn smoke() {
let (s, r) = unbounded();
s.try_send(7).unwrap();
assert_eq!(r.try_recv(), Ok(7));
s.send(8).unwrap();
assert_eq!(r.recv(), Ok(8));
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
}
#[test]
fn capacity() {
let (s, r) = unbounded::<()>();
assert_eq!(s.capacity(), None);
assert_eq!(r.capacity(), None);
}
#[test]
fn len_empty_full() {
let (s, r) = unbounded();
assert_eq!(s.len(), 0);
assert_eq!(s.is_empty(), true);
assert_eq!(s.is_full(), false);
assert_eq!(r.len(), 0);
assert_eq!(r.is_empty(), true);
assert_eq!(r.is_full(), false);
s.send(()).unwrap();
assert_eq!(s.len(), 1);
assert_eq!(s.is_empty(), false);
assert_eq!(s.is_full(), false);
assert_eq!(r.len(), 1);
assert_eq!(r.is_empty(), false);
assert_eq!(r.is_full(), false);
r.recv().unwrap();
assert_eq!(s.len(), 0);
assert_eq!(s.is_empty(), true);
assert_eq!(s.is_full(), false);
assert_eq!(r.len(), 0);
assert_eq!(r.is_empty(), true);
assert_eq!(r.is_full(), false);
}
#[test]
fn try_recv() {
let (s, r) = unbounded();
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
thread::sleep(ms(1500));
assert_eq!(r.try_recv(), Ok(7));
thread::sleep(ms(500));
assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
s.send(7).unwrap();
});
})
.unwrap();
}
#[test]
fn recv() {
let (s, r) = unbounded();
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.recv(), Ok(7));
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(8));
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(9));
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
s.send(7).unwrap();
s.send(8).unwrap();
s.send(9).unwrap();
});
})
.unwrap();
}
#[test]
fn recv_timeout() {
let (s, r) = unbounded::<i32>();
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
assert_eq!(r.recv_timeout(ms(1000)), Ok(7));
assert_eq!(
r.recv_timeout(ms(1000)),
Err(RecvTimeoutError::Disconnected)
);
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
s.send(7).unwrap();
});
})
.unwrap();
}
#[test]
fn try_send() {
let (s, r) = unbounded();
for i in 0..1000 {
assert_eq!(s.try_send(i), Ok(()));
}
drop(r);
assert_eq!(s.try_send(777), Err(TrySendError::Disconnected(777)));
}
#[test]
fn send() {
let (s, r) = unbounded();
for i in 0..1000 {
assert_eq!(s.send(i), Ok(()));
}
drop(r);
assert_eq!(s.send(777), Err(SendError(777)));
}
#[test]
fn send_timeout() {
let (s, r) = unbounded();
for i in 0..1000 {
assert_eq!(s.send_timeout(i, ms(i as u64)), Ok(()));
}
drop(r);
assert_eq!(
s.send_timeout(777, ms(0)),
Err(SendTimeoutError::Disconnected(777))
);
}
#[test]
fn send_after_disconnect() {
let (s, r) = unbounded();
s.send(1).unwrap();
s.send(2).unwrap();
s.send(3).unwrap();
drop(r);
assert_eq!(s.send(4), Err(SendError(4)));
assert_eq!(s.try_send(5), Err(TrySendError::Disconnected(5)));
assert_eq!(
s.send_timeout(6, ms(0)),
Err(SendTimeoutError::Disconnected(6))
);
}
#[test]
fn recv_after_disconnect() {
let (s, r) = unbounded();
s.send(1).unwrap();
s.send(2).unwrap();
s.send(3).unwrap();
drop(s);
assert_eq!(r.recv(), Ok(1));
assert_eq!(r.recv(), Ok(2));
assert_eq!(r.recv(), Ok(3));
assert!(r.recv().is_err());
}
#[test]
fn len() {
let (s, r) = unbounded();
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
for i in 0..50 {
s.send(i).unwrap();
assert_eq!(s.len(), i + 1);
}
for i in 0..50 {
r.recv().unwrap();
assert_eq!(r.len(), 50 - i - 1);
}
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
}
#[test]
fn disconnect_wakes_receiver() {
let (s, r) = unbounded::<()>();
scope(|scope| {
scope.spawn(move |_| {
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
drop(s);
});
})
.unwrap();
}
#[test]
fn spsc() {
const COUNT: usize = 100_000;
let (s, r) = unbounded();
scope(|scope| {
scope.spawn(move |_| {
for i in 0..COUNT {
assert_eq!(r.recv(), Ok(i));
}
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
for i in 0..COUNT {
s.send(i).unwrap();
}
});
})
.unwrap();
}
#[test]
fn mpmc() {
const COUNT: usize = 25_000;
const THREADS: usize = 4;
let (s, r) = unbounded::<usize>();
let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();
scope(|scope| {
for _ in 0..THREADS {
scope.spawn(|_| {
for _ in 0..COUNT {
let n = r.recv().unwrap();
v[n].fetch_add(1, Ordering::SeqCst);
}
});
}
for _ in 0..THREADS {
scope.spawn(|_| {
for i in 0..COUNT {
s.send(i).unwrap();
}
});
}
})
.unwrap();
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
for c in v {
assert_eq!(c.load(Ordering::SeqCst), THREADS);
}
}
#[test]
fn stress_oneshot() {
const COUNT: usize = 10_000;
for _ in 0..COUNT {
let (s, r) = unbounded();
scope(|scope| {
scope.spawn(|_| r.recv().unwrap());
scope.spawn(|_| s.send(0).unwrap());
})
.unwrap();
}
}
#[test]
fn stress_iter() {
const COUNT: usize = 100_000;
let (request_s, request_r) = unbounded();
let (response_s, response_r) = unbounded();
scope(|scope| {
scope.spawn(move |_| {
let mut count = 0;
loop {
for x in response_r.try_iter() {
count += x;
if count == COUNT {
return;
}
}
request_s.send(()).unwrap();
}
});
for _ in request_r.iter() {
if response_s.send(1).is_err() {
break;
}
}
})
.unwrap();
}
#[test]
fn stress_timeout_two_threads() {
const COUNT: usize = 100;
let (s, r) = unbounded();
scope(|scope| {
scope.spawn(|_| {
for i in 0..COUNT {
if i % 2 == 0 {
thread::sleep(ms(50));
}
s.send(i).unwrap();
}
});
scope.spawn(|_| {
for i in 0..COUNT {
if i % 2 == 0 {
thread::sleep(ms(50));
}
loop {
if let Ok(x) = r.recv_timeout(ms(10)) {
assert_eq!(x, i);
break;
}
}
}
});
})
.unwrap();
}
#[test]
fn drops() {
static DROPS: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, PartialEq)]
struct DropCounter;
impl Drop for DropCounter {
fn drop(&mut self) {
DROPS.fetch_add(1, Ordering::SeqCst);
}
}
let mut rng = thread_rng();
for _ in 0..100 {
let steps = rng.gen_range(0..10_000);
let additional = rng.gen_range(0..1000);
DROPS.store(0, Ordering::SeqCst);
let (s, r) = unbounded::<DropCounter>();
scope(|scope| {
scope.spawn(|_| {
for _ in 0..steps {
r.recv().unwrap();
}
});
scope.spawn(|_| {
for _ in 0..steps {
s.send(DropCounter).unwrap();
}
});
})
.unwrap();
for _ in 0..additional {
s.try_send(DropCounter).unwrap();
}
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
drop(s);
drop(r);
assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional);
}
}
#[test]
fn linearizable() {
const COUNT: usize = 25_000;
const THREADS: usize = 4;
let (s, r) = unbounded();
scope(|scope| {
for _ in 0..THREADS {
scope.spawn(|_| {
for _ in 0..COUNT {
s.send(0).unwrap();
r.try_recv().unwrap();
}
});
}
})
.unwrap();
}
// #[test]
// fn fairness() {
// const COUNT: usize = 10_000;
// let (s1, r1) = unbounded::<()>();
// let (s2, r2) = unbounded::<()>();
// for _ in 0..COUNT {
// s1.send(()).unwrap();
// s2.send(()).unwrap();
// }
// let mut hits = [0usize; 2];
// for _ in 0..COUNT {
// select! {
// recv(r1) -> _ => hits[0] += 1,
// recv(r2) -> _ => hits[1] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// #[test]
// fn fairness_duplicates() {
// const COUNT: usize = 10_000;
// let (s, r) = unbounded();
// for _ in 0..COUNT {
// s.send(()).unwrap();
// }
// let mut hits = [0usize; 5];
// for _ in 0..COUNT {
// select! {
// recv(r) -> _ => hits[0] += 1,
// recv(r) -> _ => hits[1] += 1,
// recv(r) -> _ => hits[2] += 1,
// recv(r) -> _ => hits[3] += 1,
// recv(r) -> _ => hits[4] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// #[test]
// fn recv_in_send() {
// let (s, r) = unbounded();
// s.send(()).unwrap();
// select! {
// send(s, assert_eq!(r.recv(), Ok(()))) -> _ => {}
// }
// }
#[test]
fn channel_through_channel() {
const COUNT: usize = 1000;
type T = Box<dyn Any + Send>;
let (s, r) = unbounded::<T>();
scope(|scope| {
scope.spawn(move |_| {
let mut s = s;
for _ in 0..COUNT {
let (new_s, new_r) = unbounded();
let new_r: T = Box::new(Some(new_r));
s.send(new_r).unwrap();
s = new_s;
}
});
scope.spawn(move |_| {
let mut r = r;
for _ in 0..COUNT {
r = r
.recv()
.unwrap()
.downcast_mut::<Option<Receiver<T>>>()
.unwrap()
.take()
.unwrap()
}
});
})
.unwrap();
}

39
vendor/flume/tests/method_sharing.rs vendored Normal file
View File

@ -0,0 +1,39 @@
#[cfg(feature = "async")]
use flume::*;
#[cfg(feature = "async")]
#[async_std::test]
async fn sender() {
let (sender, receiver) = bounded(1);
let sender_fut = sender.send_async(());
assert_eq!(sender.is_disconnected(), sender_fut.is_disconnected());
assert_eq!(sender.is_empty(), sender_fut.is_empty());
assert_eq!(sender.is_full(), sender_fut.is_full());
assert_eq!(sender.len(), sender_fut.len());
assert_eq!(sender.capacity(), sender_fut.capacity());
let sender_sink = sender.sink();
assert_eq!(sender.is_disconnected(), sender_sink.is_disconnected());
assert_eq!(sender.is_empty(), sender_sink.is_empty());
assert_eq!(sender.is_full(), sender_sink.is_full());
assert_eq!(sender.len(), sender_sink.len());
assert_eq!(sender.capacity(), sender_sink.capacity());
let receiver_fut = receiver.recv_async();
assert_eq!(receiver.is_disconnected(), receiver_fut.is_disconnected());
assert_eq!(receiver.is_empty(), receiver_fut.is_empty());
assert_eq!(receiver.is_full(), receiver_fut.is_full());
assert_eq!(receiver.len(), receiver_fut.len());
assert_eq!(receiver.capacity(), receiver_fut.capacity());
let receiver_stream = receiver.stream();
assert_eq!(
receiver.is_disconnected(),
receiver_stream.is_disconnected()
);
assert_eq!(receiver.is_empty(), receiver_stream.is_empty());
assert_eq!(receiver.is_full(), receiver_stream.is_full());
assert_eq!(receiver.len(), receiver_stream.len());
assert_eq!(receiver.capacity(), receiver_stream.capacity());
}

2095
vendor/flume/tests/mpsc.rs vendored Normal file

File diff suppressed because it is too large Load Diff

99
vendor/flume/tests/never.rs vendored Normal file
View File

@ -0,0 +1,99 @@
// //! Tests for the never channel flavor.
// #[macro_use]
// extern crate crossbeam_channel;
// extern crate rand;
// use std::thread;
// use std::time::{Duration, Instant};
// use crossbeam_channel::{never, tick, unbounded};
// fn ms(ms: u64) -> Duration {
// Duration::from_millis(ms)
// }
// #[test]
// fn smoke() {
// select! {
// recv(never::<i32>()) -> _ => panic!(),
// default => {}
// }
// }
// #[test]
// fn optional() {
// let (s, r) = unbounded::<i32>();
// s.send(1).unwrap();
// s.send(2).unwrap();
// let mut r = Some(&r);
// select! {
// recv(r.unwrap_or(&never())) -> _ => {}
// default => panic!(),
// }
// r = None;
// select! {
// recv(r.unwrap_or(&never())) -> _ => panic!(),
// default => {}
// }
// }
// #[test]
// fn tick_n() {
// let mut r = tick(ms(100));
// let mut step = 0;
// loop {
// select! {
// recv(r) -> _ => step += 1,
// default(ms(500)) => break,
// }
// if step == 10 {
// r = never();
// }
// }
// assert_eq!(step, 10);
// }
// #[test]
// fn capacity() {
// let r = never::<i32>();
// assert_eq!(r.capacity(), Some(0));
// }
// #[test]
// fn len_empty_full() {
// let r = never::<i32>();
// assert_eq!(r.len(), 0);
// assert_eq!(r.is_empty(), true);
// assert_eq!(r.is_full(), true);
// }
// #[test]
// fn try_recv() {
// let r = never::<i32>();
// assert!(r.try_recv().is_err());
// thread::sleep(ms(100));
// assert!(r.try_recv().is_err());
// }
// #[test]
// fn recv_timeout() {
// let start = Instant::now();
// let r = never::<i32>();
// assert!(r.recv_timeout(ms(100)).is_err());
// let now = Instant::now();
// assert!(now - start >= ms(100));
// assert!(now - start <= ms(150));
// assert!(r.recv_timeout(ms(100)).is_err());
// let now = Instant::now();
// assert!(now - start >= ms(200));
// assert!(now - start <= ms(250));
// }

837
vendor/flume/tests/ready.rs vendored Normal file
View File

@ -0,0 +1,837 @@
// //! Tests for channel readiness using the `Select` struct.
// extern crate crossbeam_channel;
// extern crate crossbeam_utils;
// use std::any::Any;
// use std::cell::Cell;
// use std::thread;
// use std::time::{Duration, Instant};
// use crossbeam_channel::{after, bounded, tick, unbounded};
// use crossbeam_channel::{Receiver, Select, TryRecvError, TrySendError};
// use crossbeam_utils::thread::scope;
// fn ms(ms: u64) -> Duration {
// Duration::from_millis(ms)
// }
// #[test]
// fn smoke1() {
// let (s1, r1) = unbounded::<usize>();
// let (s2, r2) = unbounded::<usize>();
// s1.send(1).unwrap();
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// assert_eq!(sel.ready(), 0);
// assert_eq!(r1.try_recv(), Ok(1));
// s2.send(2).unwrap();
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// assert_eq!(sel.ready(), 1);
// assert_eq!(r2.try_recv(), Ok(2));
// }
// #[test]
// fn smoke2() {
// let (_s1, r1) = unbounded::<i32>();
// let (_s2, r2) = unbounded::<i32>();
// let (_s3, r3) = unbounded::<i32>();
// let (_s4, r4) = unbounded::<i32>();
// let (s5, r5) = unbounded::<i32>();
// s5.send(5).unwrap();
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// sel.recv(&r3);
// sel.recv(&r4);
// sel.recv(&r5);
// assert_eq!(sel.ready(), 4);
// assert_eq!(r5.try_recv(), Ok(5));
// }
// #[test]
// fn disconnected() {
// let (s1, r1) = unbounded::<i32>();
// let (s2, r2) = unbounded::<i32>();
// scope(|scope| {
// scope.spawn(|_| {
// drop(s1);
// thread::sleep(ms(500));
// s2.send(5).unwrap();
// });
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.ready_timeout(ms(1000)) {
// Ok(0) => assert_eq!(r1.try_recv(), Err(TryRecvError::Disconnected)),
// _ => panic!(),
// }
// r2.recv().unwrap();
// })
// .unwrap();
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.ready_timeout(ms(1000)) {
// Ok(0) => assert_eq!(r1.try_recv(), Err(TryRecvError::Disconnected)),
// _ => panic!(),
// }
// scope(|scope| {
// scope.spawn(|_| {
// thread::sleep(ms(500));
// drop(s2);
// });
// let mut sel = Select::new();
// sel.recv(&r2);
// match sel.ready_timeout(ms(1000)) {
// Ok(0) => assert_eq!(r2.try_recv(), Err(TryRecvError::Disconnected)),
// _ => panic!(),
// }
// })
// .unwrap();
// }
// #[test]
// fn default() {
// let (s1, r1) = unbounded::<i32>();
// let (s2, r2) = unbounded::<i32>();
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// assert!(sel.try_ready().is_err());
// drop(s1);
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.try_ready() {
// Ok(0) => assert!(r1.try_recv().is_err()),
// _ => panic!(),
// }
// s2.send(2).unwrap();
// let mut sel = Select::new();
// sel.recv(&r2);
// match sel.try_ready() {
// Ok(0) => assert_eq!(r2.try_recv(), Ok(2)),
// _ => panic!(),
// }
// let mut sel = Select::new();
// sel.recv(&r2);
// assert!(sel.try_ready().is_err());
// let mut sel = Select::new();
// assert!(sel.try_ready().is_err());
// }
// #[test]
// fn timeout() {
// let (_s1, r1) = unbounded::<i32>();
// let (s2, r2) = unbounded::<i32>();
// scope(|scope| {
// scope.spawn(|_| {
// thread::sleep(ms(1500));
// s2.send(2).unwrap();
// });
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// assert!(sel.ready_timeout(ms(1000)).is_err());
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.ready_timeout(ms(1000)) {
// Ok(1) => assert_eq!(r2.try_recv(), Ok(2)),
// _ => panic!(),
// }
// })
// .unwrap();
// scope(|scope| {
// let (s, r) = unbounded::<i32>();
// scope.spawn(move |_| {
// thread::sleep(ms(500));
// drop(s);
// });
// let mut sel = Select::new();
// assert!(sel.ready_timeout(ms(1000)).is_err());
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.try_ready() {
// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
// _ => panic!(),
// }
// })
// .unwrap();
// }
// #[test]
// fn default_when_disconnected() {
// let (_, r) = unbounded::<i32>();
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.try_ready() {
// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
// _ => panic!(),
// }
// let (_, r) = unbounded::<i32>();
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready_timeout(ms(1000)) {
// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
// _ => panic!(),
// }
// let (s, _) = bounded::<i32>(0);
// let mut sel = Select::new();
// sel.send(&s);
// match sel.try_ready() {
// Ok(0) => assert_eq!(s.try_send(0), Err(TrySendError::Disconnected(0))),
// _ => panic!(),
// }
// let (s, _) = bounded::<i32>(0);
// let mut sel = Select::new();
// sel.send(&s);
// match sel.ready_timeout(ms(1000)) {
// Ok(0) => assert_eq!(s.try_send(0), Err(TrySendError::Disconnected(0))),
// _ => panic!(),
// }
// }
// #[test]
// fn default_only() {
// let start = Instant::now();
// let mut sel = Select::new();
// assert!(sel.try_ready().is_err());
// let now = Instant::now();
// assert!(now - start <= ms(50));
// let start = Instant::now();
// let mut sel = Select::new();
// assert!(sel.ready_timeout(ms(500)).is_err());
// let now = Instant::now();
// assert!(now - start >= ms(450));
// assert!(now - start <= ms(550));
// }
// #[test]
// fn unblocks() {
// let (s1, r1) = bounded::<i32>(0);
// let (s2, r2) = bounded::<i32>(0);
// scope(|scope| {
// scope.spawn(|_| {
// thread::sleep(ms(500));
// s2.send(2).unwrap();
// });
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.ready_timeout(ms(1000)) {
// Ok(1) => assert_eq!(r2.try_recv(), Ok(2)),
// _ => panic!(),
// }
// })
// .unwrap();
// scope(|scope| {
// scope.spawn(|_| {
// thread::sleep(ms(500));
// assert_eq!(r1.recv().unwrap(), 1);
// });
// let mut sel = Select::new();
// let oper1 = sel.send(&s1);
// let oper2 = sel.send(&s2);
// let oper = sel.select_timeout(ms(1000));
// match oper {
// Err(_) => panic!(),
// Ok(oper) => match oper.index() {
// i if i == oper1 => oper.send(&s1, 1).unwrap(),
// i if i == oper2 => panic!(),
// _ => unreachable!(),
// },
// }
// })
// .unwrap();
// }
// #[test]
// fn both_ready() {
// let (s1, r1) = bounded(0);
// let (s2, r2) = bounded(0);
// scope(|scope| {
// scope.spawn(|_| {
// thread::sleep(ms(500));
// s1.send(1).unwrap();
// assert_eq!(r2.recv().unwrap(), 2);
// });
// for _ in 0..2 {
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.send(&s2);
// match sel.ready() {
// 0 => assert_eq!(r1.try_recv(), Ok(1)),
// 1 => s2.try_send(2).unwrap(),
// _ => panic!(),
// }
// }
// })
// .unwrap();
// }
// #[test]
// fn cloning1() {
// scope(|scope| {
// let (s1, r1) = unbounded::<i32>();
// let (_s2, r2) = unbounded::<i32>();
// let (s3, r3) = unbounded::<()>();
// scope.spawn(move |_| {
// r3.recv().unwrap();
// drop(s1.clone());
// assert!(r3.try_recv().is_err());
// s1.send(1).unwrap();
// r3.recv().unwrap();
// });
// s3.send(()).unwrap();
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.ready() {
// 0 => drop(r1.try_recv()),
// 1 => drop(r2.try_recv()),
// _ => panic!(),
// }
// s3.send(()).unwrap();
// })
// .unwrap();
// }
// #[test]
// fn cloning2() {
// let (s1, r1) = unbounded::<()>();
// let (s2, r2) = unbounded::<()>();
// let (_s3, _r3) = unbounded::<()>();
// scope(|scope| {
// scope.spawn(move |_| {
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.ready() {
// 0 => panic!(),
// 1 => drop(r2.try_recv()),
// _ => panic!(),
// }
// });
// thread::sleep(ms(500));
// drop(s1.clone());
// s2.send(()).unwrap();
// })
// .unwrap();
// }
// #[test]
// fn preflight1() {
// let (s, r) = unbounded();
// s.send(()).unwrap();
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready() {
// 0 => drop(r.try_recv()),
// _ => panic!(),
// }
// }
// #[test]
// fn preflight2() {
// let (s, r) = unbounded();
// drop(s.clone());
// s.send(()).unwrap();
// drop(s);
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready() {
// 0 => assert_eq!(r.try_recv(), Ok(())),
// _ => panic!(),
// }
// assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
// }
// #[test]
// fn preflight3() {
// let (s, r) = unbounded();
// drop(s.clone());
// s.send(()).unwrap();
// drop(s);
// r.recv().unwrap();
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready() {
// 0 => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
// _ => panic!(),
// }
// }
// #[test]
// fn duplicate_operations() {
// let (s, r) = unbounded::<i32>();
// let hit = vec![Cell::new(false); 4];
// while hit.iter().map(|h| h.get()).any(|hit| !hit) {
// let mut sel = Select::new();
// sel.recv(&r);
// sel.recv(&r);
// sel.send(&s);
// sel.send(&s);
// match sel.ready() {
// 0 => {
// assert!(r.try_recv().is_ok());
// hit[0].set(true);
// }
// 1 => {
// assert!(r.try_recv().is_ok());
// hit[1].set(true);
// }
// 2 => {
// assert!(s.try_send(0).is_ok());
// hit[2].set(true);
// }
// 3 => {
// assert!(s.try_send(0).is_ok());
// hit[3].set(true);
// }
// _ => panic!(),
// }
// }
// }
// #[test]
// fn nesting() {
// let (s, r) = unbounded::<i32>();
// let mut sel = Select::new();
// sel.send(&s);
// match sel.ready() {
// 0 => {
// assert!(s.try_send(0).is_ok());
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready() {
// 0 => {
// assert_eq!(r.try_recv(), Ok(0));
// let mut sel = Select::new();
// sel.send(&s);
// match sel.ready() {
// 0 => {
// assert!(s.try_send(1).is_ok());
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready() {
// 0 => {
// assert_eq!(r.try_recv(), Ok(1));
// }
// _ => panic!(),
// }
// }
// _ => panic!(),
// }
// }
// _ => panic!(),
// }
// }
// _ => panic!(),
// }
// }
// #[test]
// fn stress_recv() {
// const COUNT: usize = 10_000;
// let (s1, r1) = unbounded();
// let (s2, r2) = bounded(5);
// let (s3, r3) = bounded(0);
// scope(|scope| {
// scope.spawn(|_| {
// for i in 0..COUNT {
// s1.send(i).unwrap();
// r3.recv().unwrap();
// s2.send(i).unwrap();
// r3.recv().unwrap();
// }
// });
// for i in 0..COUNT {
// for _ in 0..2 {
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// match sel.ready() {
// 0 => assert_eq!(r1.try_recv(), Ok(i)),
// 1 => assert_eq!(r2.try_recv(), Ok(i)),
// _ => panic!(),
// }
// s3.send(()).unwrap();
// }
// }
// })
// .unwrap();
// }
// #[test]
// fn stress_send() {
// const COUNT: usize = 10_000;
// let (s1, r1) = bounded(0);
// let (s2, r2) = bounded(0);
// let (s3, r3) = bounded(100);
// scope(|scope| {
// scope.spawn(|_| {
// for i in 0..COUNT {
// assert_eq!(r1.recv().unwrap(), i);
// assert_eq!(r2.recv().unwrap(), i);
// r3.recv().unwrap();
// }
// });
// for i in 0..COUNT {
// for _ in 0..2 {
// let mut sel = Select::new();
// sel.send(&s1);
// sel.send(&s2);
// match sel.ready() {
// 0 => assert!(s1.try_send(i).is_ok()),
// 1 => assert!(s2.try_send(i).is_ok()),
// _ => panic!(),
// }
// }
// s3.send(()).unwrap();
// }
// })
// .unwrap();
// }
// #[test]
// fn stress_mixed() {
// const COUNT: usize = 10_000;
// let (s1, r1) = bounded(0);
// let (s2, r2) = bounded(0);
// let (s3, r3) = bounded(100);
// scope(|scope| {
// scope.spawn(|_| {
// for i in 0..COUNT {
// s1.send(i).unwrap();
// assert_eq!(r2.recv().unwrap(), i);
// r3.recv().unwrap();
// }
// });
// for i in 0..COUNT {
// for _ in 0..2 {
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.send(&s2);
// match sel.ready() {
// 0 => assert_eq!(r1.try_recv(), Ok(i)),
// 1 => assert!(s2.try_send(i).is_ok()),
// _ => panic!(),
// }
// }
// s3.send(()).unwrap();
// }
// })
// .unwrap();
// }
// #[test]
// fn stress_timeout_two_threads() {
// const COUNT: usize = 20;
// let (s, r) = bounded(2);
// scope(|scope| {
// scope.spawn(|_| {
// for i in 0..COUNT {
// if i % 2 == 0 {
// thread::sleep(ms(500));
// }
// let done = false;
// while !done {
// let mut sel = Select::new();
// sel.send(&s);
// match sel.ready_timeout(ms(100)) {
// Err(_) => {}
// Ok(0) => {
// assert!(s.try_send(i).is_ok());
// break;
// }
// Ok(_) => panic!(),
// }
// }
// }
// });
// scope.spawn(|_| {
// for i in 0..COUNT {
// if i % 2 == 0 {
// thread::sleep(ms(500));
// }
// let mut done = false;
// while !done {
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready_timeout(ms(100)) {
// Err(_) => {}
// Ok(0) => {
// assert_eq!(r.try_recv(), Ok(i));
// done = true;
// }
// Ok(_) => panic!(),
// }
// }
// }
// });
// })
// .unwrap();
// }
// #[test]
// fn send_recv_same_channel() {
// let (s, r) = bounded::<i32>(0);
// let mut sel = Select::new();
// sel.send(&s);
// sel.recv(&r);
// assert!(sel.ready_timeout(ms(100)).is_err());
// let (s, r) = unbounded::<i32>();
// let mut sel = Select::new();
// sel.send(&s);
// sel.recv(&r);
// match sel.ready_timeout(ms(100)) {
// Err(_) => panic!(),
// Ok(0) => assert!(s.try_send(0).is_ok()),
// Ok(_) => panic!(),
// }
// }
// #[test]
// fn channel_through_channel() {
// const COUNT: usize = 1000;
// type T = Box<dyn Any + Send>;
// for cap in 1..4 {
// let (s, r) = bounded::<T>(cap);
// scope(|scope| {
// scope.spawn(move |_| {
// let mut s = s;
// for _ in 0..COUNT {
// let (new_s, new_r) = bounded(cap);
// let new_r: T = Box::new(Some(new_r));
// {
// let mut sel = Select::new();
// sel.send(&s);
// match sel.ready() {
// 0 => assert!(s.try_send(new_r).is_ok()),
// _ => panic!(),
// }
// }
// s = new_s;
// }
// });
// scope.spawn(move |_| {
// let mut r = r;
// for _ in 0..COUNT {
// let new = {
// let mut sel = Select::new();
// sel.recv(&r);
// match sel.ready() {
// 0 => r
// .try_recv()
// .unwrap()
// .downcast_mut::<Option<Receiver<T>>>()
// .unwrap()
// .take()
// .unwrap(),
// _ => panic!(),
// }
// };
// r = new;
// }
// });
// })
// .unwrap();
// }
// }
// #[test]
// fn fairness1() {
// const COUNT: usize = 10_000;
// let (s1, r1) = bounded::<()>(COUNT);
// let (s2, r2) = unbounded::<()>();
// for _ in 0..COUNT {
// s1.send(()).unwrap();
// s2.send(()).unwrap();
// }
// let hits = vec![Cell::new(0usize); 4];
// for _ in 0..COUNT {
// let after = after(ms(0));
// let tick = tick(ms(0));
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// sel.recv(&after);
// sel.recv(&tick);
// match sel.ready() {
// 0 => {
// r1.try_recv().unwrap();
// hits[0].set(hits[0].get() + 1);
// }
// 1 => {
// r2.try_recv().unwrap();
// hits[1].set(hits[1].get() + 1);
// }
// 2 => {
// after.try_recv().unwrap();
// hits[2].set(hits[2].get() + 1);
// }
// 3 => {
// tick.try_recv().unwrap();
// hits[3].set(hits[3].get() + 1);
// }
// _ => panic!(),
// }
// }
// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 2));
// }
// #[test]
// fn fairness2() {
// const COUNT: usize = 10_000;
// let (s1, r1) = unbounded::<()>();
// let (s2, r2) = bounded::<()>(1);
// let (s3, r3) = bounded::<()>(0);
// scope(|scope| {
// scope.spawn(|_| {
// for _ in 0..COUNT {
// let mut sel = Select::new();
// let mut oper1 = None;
// let mut oper2 = None;
// if s1.is_empty() {
// oper1 = Some(sel.send(&s1));
// }
// if s2.is_empty() {
// oper2 = Some(sel.send(&s2));
// }
// let oper3 = sel.send(&s3);
// let oper = sel.select();
// match oper.index() {
// i if Some(i) == oper1 => assert!(oper.send(&s1, ()).is_ok()),
// i if Some(i) == oper2 => assert!(oper.send(&s2, ()).is_ok()),
// i if i == oper3 => assert!(oper.send(&s3, ()).is_ok()),
// _ => unreachable!(),
// }
// }
// });
// let hits = vec![Cell::new(0usize); 3];
// for _ in 0..COUNT {
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// sel.recv(&r3);
// loop {
// match sel.ready() {
// 0 => {
// if r1.try_recv().is_ok() {
// hits[0].set(hits[0].get() + 1);
// break;
// }
// }
// 1 => {
// if r2.try_recv().is_ok() {
// hits[1].set(hits[1].get() + 1);
// break;
// }
// }
// 2 => {
// if r3.try_recv().is_ok() {
// hits[2].set(hits[2].get() + 1);
// break;
// }
// }
// _ => unreachable!(),
// }
// }
// }
// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 10));
// })
// .unwrap();
// }

114
vendor/flume/tests/same_channel.rs vendored Normal file
View File

@ -0,0 +1,114 @@
// extern crate crossbeam_channel;
// use std::time::Duration;
// use crossbeam_channel::{after, bounded, never, tick, unbounded};
// fn ms(ms: u64) -> Duration {
// Duration::from_millis(ms)
// }
// #[test]
// fn after_same_channel() {
// let r = after(ms(50));
// let r2 = r.clone();
// assert!(r.same_channel(&r2));
// let r3 = after(ms(50));
// assert!(!r.same_channel(&r3));
// assert!(!r2.same_channel(&r3));
// let r4 = after(ms(100));
// assert!(!r.same_channel(&r4));
// assert!(!r2.same_channel(&r4));
// }
// #[test]
// fn array_same_channel() {
// let (s, r) = bounded::<usize>(1);
// let s2 = s.clone();
// assert!(s.same_channel(&s2));
// let r2 = r.clone();
// assert!(r.same_channel(&r2));
// let (s3, r3) = bounded::<usize>(1);
// assert!(!s.same_channel(&s3));
// assert!(!s2.same_channel(&s3));
// assert!(!r.same_channel(&r3));
// assert!(!r2.same_channel(&r3));
// }
// #[test]
// fn list_same_channel() {
// let (s, r) = unbounded::<usize>();
// let s2 = s.clone();
// assert!(s.same_channel(&s2));
// let r2 = r.clone();
// assert!(r.same_channel(&r2));
// let (s3, r3) = unbounded::<usize>();
// assert!(!s.same_channel(&s3));
// assert!(!s2.same_channel(&s3));
// assert!(!r.same_channel(&r3));
// assert!(!r2.same_channel(&r3));
// }
// #[test]
// fn never_same_channel() {
// let r = never::<usize>();
// let r2 = r.clone();
// assert!(r.same_channel(&r2));
// // Never channel are always equal to one another.
// let r3 = never::<usize>();
// assert!(r.same_channel(&r3));
// assert!(r2.same_channel(&r3));
// }
// #[test]
// fn tick_same_channel() {
// let r = tick(ms(50));
// let r2 = r.clone();
// assert!(r.same_channel(&r2));
// let r3 = tick(ms(50));
// assert!(!r.same_channel(&r3));
// assert!(!r2.same_channel(&r3));
// let r4 = tick(ms(100));
// assert!(!r.same_channel(&r4));
// assert!(!r2.same_channel(&r4));
// }
// #[test]
// fn zero_same_channel() {
// let (s, r) = bounded::<usize>(0);
// let s2 = s.clone();
// assert!(s.same_channel(&s2));
// let r2 = r.clone();
// assert!(r.same_channel(&r2));
// let (s3, r3) = bounded::<usize>(0);
// assert!(!s.same_channel(&s3));
// assert!(!s2.same_channel(&s3));
// assert!(!r.same_channel(&r3));
// assert!(!r2.same_channel(&r3));
// }
// #[test]
// fn different_flavors_same_channel() {
// let (s1, r1) = bounded::<usize>(0);
// let (s2, r2) = unbounded::<usize>();
// assert!(!s1.same_channel(&s2));
// assert!(!r1.same_channel(&r2));
// }

1304
vendor/flume/tests/select.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1440
vendor/flume/tests/select_macro.rs vendored Normal file

File diff suppressed because it is too large Load Diff

255
vendor/flume/tests/stream.rs vendored Normal file
View File

@ -0,0 +1,255 @@
#[cfg(feature = "async")]
use {
flume::*,
futures::{stream::FuturesUnordered, StreamExt, TryFutureExt},
async_std::prelude::FutureExt,
std::time::Duration,
};
use futures::{stream, Stream};
#[cfg(feature = "async")]
#[test]
fn stream_recv() {
let (tx, rx) = unbounded();
let t = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(250));
tx.send(42u32).unwrap();
println!("sent");
});
async_std::task::block_on(async {
println!("receiving...");
let x = rx.stream().next().await;
println!("received");
assert_eq!(x, Some(42));
});
t.join().unwrap();
}
#[cfg(feature = "async")]
#[test]
fn stream_recv_disconnect() {
let (tx, rx) = bounded::<i32>(0);
let t = std::thread::spawn(move || {
tx.send(42);
std::thread::sleep(std::time::Duration::from_millis(250));
drop(tx)
});
async_std::task::block_on(async {
let mut stream = rx.into_stream();
assert_eq!(stream.next().await, Some(42));
assert_eq!(stream.next().await, None);
});
t.join().unwrap();
}
#[cfg(feature = "async")]
#[test]
fn stream_recv_drop_recv() {
let (tx, rx) = bounded::<i32>(10);
let rx2 = rx.clone();
let mut stream = rx.into_stream();
async_std::task::block_on(async {
let res = async_std::future::timeout(
std::time::Duration::from_millis(500),
stream.next()
).await;
assert!(res.is_err());
});
let t = std::thread::spawn(move || {
async_std::task::block_on(async {
rx2.stream().next().await
})
});
std::thread::sleep(std::time::Duration::from_millis(500));
tx.send(42).unwrap();
drop(stream);
assert_eq!(t.join().unwrap(), Some(42))
}
#[cfg(feature = "async")]
#[test]
fn r#stream_drop_send_disconnect() {
let (tx, rx) = bounded::<i32>(1);
let t = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(250));
drop(tx);
});
async_std::task::block_on(async {
let mut stream = rx.into_stream();
assert_eq!(stream.next().await, None);
});
t.join().unwrap();
}
#[cfg(feature = "async")]
#[async_std::test]
async fn stream_send_1_million_no_drop_or_reorder() {
#[derive(Debug)]
enum Message {
Increment {
old: u64,
},
ReturnCount,
}
let (tx, rx) = unbounded();
let t = async_std::task::spawn(async move {
let mut count = 0u64;
let mut stream = rx.into_stream();
while let Some(Message::Increment { old }) = stream.next().await {
assert_eq!(old, count);
count += 1;
}
count
});
for next in 0..1_000_000 {
tx.send(Message::Increment { old: next }).unwrap();
}
tx.send(Message::ReturnCount).unwrap();
let count = t.await;
assert_eq!(count, 1_000_000)
}
#[cfg(feature = "async")]
#[async_std::test]
async fn parallel_streams_and_async_recv() {
let (tx, rx) = flume::unbounded();
let rx = &rx;
let send_fut = async move {
let n_sends: usize = 100000;
for _ in 0..n_sends {
tx.send_async(()).await.unwrap();
}
};
async_std::task::spawn(
send_fut
.timeout(Duration::from_secs(5))
.map_err(|_| panic!("Send timed out!"))
);
let mut futures_unordered = (0..250)
.map(|n| async move {
if n % 2 == 0 {
let mut stream = rx.stream();
while let Some(()) = stream.next().await {}
} else {
while let Ok(()) = rx.recv_async().await {}
}
})
.collect::<FuturesUnordered<_>>();
let recv_fut = async {
while futures_unordered.next().await.is_some() {}
};
recv_fut
.timeout(Duration::from_secs(5))
.map_err(|_| panic!("Receive timed out!"))
.await
.unwrap();
}
#[cfg(feature = "async")]
#[test]
fn stream_no_double_wake() {
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::pin::Pin;
use std::task::Context;
use futures::task::{waker, ArcWake};
use futures::Stream;
let count = Arc::new(AtomicUsize::new(0));
// all this waker does is count how many times it is called
struct CounterWaker {
count: Arc<AtomicUsize>,
}
impl ArcWake for CounterWaker {
fn wake_by_ref(arc_self: &Arc<Self>) {
arc_self.count.fetch_add(1, Ordering::SeqCst);
}
}
// create waker and context
let w = CounterWaker {
count: count.clone(),
};
let w = waker(Arc::new(w));
let cx = &mut Context::from_waker(&w);
// create unbounded channel
let (tx, rx) = unbounded::<()>();
let mut stream = rx.stream();
// register waker with stream
let _ = Pin::new(&mut stream).poll_next(cx);
// send multiple items
tx.send(()).unwrap();
tx.send(()).unwrap();
tx.send(()).unwrap();
// verify that stream is only woken up once.
assert_eq!(count.load(Ordering::SeqCst), 1);
}
#[cfg(feature = "async")]
#[async_std::test]
async fn stream_forward_issue_55() { // https://github.com/zesterer/flume/issues/55
fn dummy_stream() -> impl Stream<Item = usize> {
stream::unfold(0, |count| async move {
if count < 1000 {
Some((count, count + 1))
} else {
None
}
})
}
let (send_task, recv_task) = {
use futures::SinkExt;
let (tx, rx) = flume::bounded(100);
let send_task = dummy_stream()
.map(|i| Ok(i))
.forward(tx.into_sink().sink_map_err(|e| {
panic!("send error:{:#?}", e)
}));
let recv_task = rx
.into_stream()
.for_each(|item| async move {});
(send_task, recv_task)
};
let jh = async_std::task::spawn(send_task);
async_std::task::block_on(recv_task);
jh.await.unwrap();
}

53
vendor/flume/tests/thread_locals.rs vendored Normal file
View File

@ -0,0 +1,53 @@
// //! Tests that make sure accessing thread-locals while exiting the thread doesn't cause panics.
// extern crate crossbeam_utils;
// use std::thread;
// use std::time::Duration;
// use flume::unbounded;
// use crossbeam_utils::thread::scope;
// fn ms(ms: u64) -> Duration {
// Duration::from_millis(ms)
// }
// #[test]
// #[cfg_attr(target_os = "macos", ignore = "TLS is destroyed too early on macOS")]
// fn use_while_exiting() {
// struct Foo;
// impl Drop for Foo {
// fn drop(&mut self) {
// // A blocking operation after the thread-locals have been dropped. This will attempt to
// // use the thread-locals and must not panic.
// let (_s, r) = unbounded::<()>();
// select! {
// recv(r) -> _ => {}
// default(ms(100)) => {}
// }
// }
// }
// thread_local! {
// static FOO: Foo = Foo;
// }
// let (s, r) = unbounded::<()>();
// scope(|scope| {
// scope.spawn(|_| {
// // First initialize `FOO`, then the thread-locals related to crossbeam-channel.
// FOO.with(|_| ());
// r.recv().unwrap();
// // At thread exit, thread-locals related to crossbeam-channel get dropped first and
// // `FOO` is dropped last.
// });
// scope.spawn(|_| {
// thread::sleep(ms(100));
// s.send(()).unwrap();
// });
// })
// .unwrap();
// }

353
vendor/flume/tests/tick.rs vendored Normal file
View File

@ -0,0 +1,353 @@
// //! Tests for the tick channel flavor.
// #[macro_use]
// extern crate crossbeam_channel;
// extern crate crossbeam_utils;
// extern crate rand;
// use std::sync::atomic::AtomicUsize;
// use std::sync::atomic::Ordering;
// use std::thread;
// use std::time::{Duration, Instant};
// use crossbeam_channel::{after, tick, Select, TryRecvError};
// use crossbeam_utils::thread::scope;
// fn ms(ms: u64) -> Duration {
// Duration::from_millis(ms)
// }
// #[test]
// fn fire() {
// let start = Instant::now();
// let r = tick(ms(50));
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// thread::sleep(ms(100));
// let fired = r.try_recv().unwrap();
// assert!(start < fired);
// assert!(fired - start >= ms(50));
// let now = Instant::now();
// assert!(fired < now);
// assert!(now - fired >= ms(50));
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// select! {
// recv(r) -> _ => panic!(),
// default => {}
// }
// select! {
// recv(r) -> _ => {}
// recv(tick(ms(200))) -> _ => panic!(),
// }
// }
// #[test]
// fn intervals() {
// let start = Instant::now();
// let r = tick(ms(50));
// let t1 = r.recv().unwrap();
// assert!(start + ms(50) <= t1);
// assert!(start + ms(100) > t1);
// thread::sleep(ms(300));
// let t2 = r.try_recv().unwrap();
// assert!(start + ms(100) <= t2);
// assert!(start + ms(150) > t2);
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// let t3 = r.recv().unwrap();
// assert!(start + ms(400) <= t3);
// assert!(start + ms(450) > t3);
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// }
// #[test]
// fn capacity() {
// const COUNT: usize = 10;
// for i in 0..COUNT {
// let r = tick(ms(i as u64));
// assert_eq!(r.capacity(), Some(1));
// }
// }
// #[test]
// fn len_empty_full() {
// let r = tick(ms(50));
// assert_eq!(r.len(), 0);
// assert_eq!(r.is_empty(), true);
// assert_eq!(r.is_full(), false);
// thread::sleep(ms(100));
// assert_eq!(r.len(), 1);
// assert_eq!(r.is_empty(), false);
// assert_eq!(r.is_full(), true);
// r.try_recv().unwrap();
// assert_eq!(r.len(), 0);
// assert_eq!(r.is_empty(), true);
// assert_eq!(r.is_full(), false);
// }
// #[test]
// fn try_recv() {
// let r = tick(ms(200));
// assert!(r.try_recv().is_err());
// thread::sleep(ms(100));
// assert!(r.try_recv().is_err());
// thread::sleep(ms(200));
// assert!(r.try_recv().is_ok());
// assert!(r.try_recv().is_err());
// thread::sleep(ms(200));
// assert!(r.try_recv().is_ok());
// assert!(r.try_recv().is_err());
// }
// #[test]
// fn recv() {
// let start = Instant::now();
// let r = tick(ms(50));
// let fired = r.recv().unwrap();
// assert!(start < fired);
// assert!(fired - start >= ms(50));
// let now = Instant::now();
// assert!(fired < now);
// assert!(now - fired < fired - start);
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
// }
// #[test]
// fn recv_timeout() {
// let start = Instant::now();
// let r = tick(ms(200));
// assert!(r.recv_timeout(ms(100)).is_err());
// let now = Instant::now();
// assert!(now - start >= ms(100));
// assert!(now - start <= ms(150));
// let fired = r.recv_timeout(ms(200)).unwrap();
// assert!(fired - start >= ms(200));
// assert!(fired - start <= ms(250));
// assert!(r.recv_timeout(ms(100)).is_err());
// let now = Instant::now();
// assert!(now - start >= ms(300));
// assert!(now - start <= ms(350));
// let fired = r.recv_timeout(ms(200)).unwrap();
// assert!(fired - start >= ms(400));
// assert!(fired - start <= ms(450));
// }
// #[test]
// fn recv_two() {
// let r1 = tick(ms(50));
// let r2 = tick(ms(50));
// scope(|scope| {
// scope.spawn(|_| {
// for _ in 0..10 {
// select! {
// recv(r1) -> _ => {}
// recv(r2) -> _ => {}
// }
// }
// });
// scope.spawn(|_| {
// for _ in 0..10 {
// select! {
// recv(r1) -> _ => {}
// recv(r2) -> _ => {}
// }
// }
// });
// })
// .unwrap();
// }
// #[test]
// fn recv_race() {
// select! {
// recv(tick(ms(50))) -> _ => {}
// recv(tick(ms(100))) -> _ => panic!(),
// }
// select! {
// recv(tick(ms(100))) -> _ => panic!(),
// recv(tick(ms(50))) -> _ => {}
// }
// }
// #[test]
// fn stress_default() {
// const COUNT: usize = 10;
// for _ in 0..COUNT {
// select! {
// recv(tick(ms(0))) -> _ => {}
// default => panic!(),
// }
// }
// for _ in 0..COUNT {
// select! {
// recv(tick(ms(100))) -> _ => panic!(),
// default => {}
// }
// }
// }
// #[test]
// fn select() {
// const THREADS: usize = 4;
// let hits = AtomicUsize::new(0);
// let r1 = tick(ms(200));
// let r2 = tick(ms(300));
// scope(|scope| {
// for _ in 0..THREADS {
// scope.spawn(|_| {
// let timeout = after(ms(1100));
// loop {
// let mut sel = Select::new();
// let oper1 = sel.recv(&r1);
// let oper2 = sel.recv(&r2);
// let oper3 = sel.recv(&timeout);
// let oper = sel.select();
// match oper.index() {
// i if i == oper1 => {
// oper.recv(&r1).unwrap();
// hits.fetch_add(1, Ordering::SeqCst);
// }
// i if i == oper2 => {
// oper.recv(&r2).unwrap();
// hits.fetch_add(1, Ordering::SeqCst);
// }
// i if i == oper3 => {
// oper.recv(&timeout).unwrap();
// break;
// }
// _ => unreachable!(),
// }
// }
// });
// }
// })
// .unwrap();
// assert_eq!(hits.load(Ordering::SeqCst), 8);
// }
// #[test]
// fn ready() {
// const THREADS: usize = 4;
// let hits = AtomicUsize::new(0);
// let r1 = tick(ms(200));
// let r2 = tick(ms(300));
// scope(|scope| {
// for _ in 0..THREADS {
// scope.spawn(|_| {
// let timeout = after(ms(1100));
// 'outer: loop {
// let mut sel = Select::new();
// sel.recv(&r1);
// sel.recv(&r2);
// sel.recv(&timeout);
// loop {
// match sel.ready() {
// 0 => {
// if r1.try_recv().is_ok() {
// hits.fetch_add(1, Ordering::SeqCst);
// break;
// }
// }
// 1 => {
// if r2.try_recv().is_ok() {
// hits.fetch_add(1, Ordering::SeqCst);
// break;
// }
// }
// 2 => {
// if timeout.try_recv().is_ok() {
// break 'outer;
// }
// }
// _ => unreachable!(),
// }
// }
// }
// });
// }
// })
// .unwrap();
// assert_eq!(hits.load(Ordering::SeqCst), 8);
// }
// #[test]
// fn fairness() {
// const COUNT: usize = 30;
// for &dur in &[0, 1] {
// let mut hits = [0usize; 2];
// for _ in 0..COUNT {
// let r1 = tick(ms(dur));
// let r2 = tick(ms(dur));
// for _ in 0..COUNT {
// select! {
// recv(r1) -> _ => hits[0] += 1,
// recv(r2) -> _ => hits[1] += 1,
// }
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// }
// #[test]
// fn fairness_duplicates() {
// const COUNT: usize = 30;
// for &dur in &[0, 1] {
// let mut hits = [0usize; 5];
// for _ in 0..COUNT {
// let r = tick(ms(dur));
// for _ in 0..COUNT {
// select! {
// recv(r) -> _ => hits[0] += 1,
// recv(r) -> _ => hits[1] += 1,
// recv(r) -> _ => hits[2] += 1,
// recv(r) -> _ => hits[3] += 1,
// recv(r) -> _ => hits[4] += 1,
// }
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// }
// }

557
vendor/flume/tests/zero.rs vendored Normal file
View File

@ -0,0 +1,557 @@
//! Tests for the zero channel flavor.
extern crate crossbeam_utils;
extern crate rand;
use std::any::Any;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::thread;
use std::time::Duration;
use flume::{bounded, Receiver};
use flume::{RecvError, RecvTimeoutError, TryRecvError};
use flume::{SendError, SendTimeoutError, TrySendError};
use crossbeam_utils::thread::scope;
use rand::{thread_rng, Rng};
fn ms(ms: u64) -> Duration {
Duration::from_millis(ms)
}
#[test]
fn smoke() {
let (s, r) = bounded(0);
assert_eq!(s.try_send(7), Err(TrySendError::Full(7)));
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
}
#[test]
fn capacity() {
let (s, r) = bounded::<()>(0);
assert_eq!(s.capacity(), Some(0));
assert_eq!(r.capacity(), Some(0));
}
#[test]
fn len_empty_full() {
let (s, r) = bounded(0);
assert_eq!(s.len(), 0);
assert_eq!(s.is_empty(), true);
assert_eq!(s.is_full(), true);
assert_eq!(r.len(), 0);
assert_eq!(r.is_empty(), true);
assert_eq!(r.is_full(), true);
scope(|scope| {
scope.spawn(|_| s.send(0).unwrap());
scope.spawn(|_| r.recv().unwrap());
})
.unwrap();
assert_eq!(s.len(), 0);
assert_eq!(s.is_empty(), true);
assert_eq!(s.is_full(), true);
assert_eq!(r.len(), 0);
assert_eq!(r.is_empty(), true);
assert_eq!(r.is_full(), true);
}
#[test]
fn try_recv() {
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
thread::sleep(ms(1500));
assert_eq!(r.try_recv(), Ok(7));
thread::sleep(ms(500));
assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
s.send(7).unwrap();
});
})
.unwrap();
}
#[test]
fn recv() {
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.recv(), Ok(7));
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(8));
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(9));
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
s.send(7).unwrap();
s.send(8).unwrap();
s.send(9).unwrap();
});
})
.unwrap();
}
#[test]
fn recv_timeout() {
let (s, r) = bounded::<i32>(0);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
assert_eq!(r.recv_timeout(ms(1000)), Ok(7));
assert_eq!(
r.recv_timeout(ms(1000)),
Err(RecvTimeoutError::Disconnected)
);
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
s.send(7).unwrap();
});
})
.unwrap();
}
#[test]
fn try_send() {
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(s.try_send(7), Err(TrySendError::Full(7)));
thread::sleep(ms(1500));
assert_eq!(s.try_send(8), Ok(()));
thread::sleep(ms(500));
assert_eq!(s.try_send(9), Err(TrySendError::Disconnected(9)));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
assert_eq!(r.recv(), Ok(8));
});
})
.unwrap();
}
#[test]
fn send() {
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
s.send(7).unwrap();
thread::sleep(ms(1000));
s.send(8).unwrap();
thread::sleep(ms(1000));
s.send(9).unwrap();
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
assert_eq!(r.recv(), Ok(7));
assert_eq!(r.recv(), Ok(8));
assert_eq!(r.recv(), Ok(9));
});
})
.unwrap();
}
#[test]
fn send_timeout() {
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(
s.send_timeout(7, ms(1000)),
Err(SendTimeoutError::Timeout(7))
);
assert_eq!(s.send_timeout(8, ms(1000)), Ok(()));
assert_eq!(
s.send_timeout(9, ms(1000)),
Err(SendTimeoutError::Disconnected(9))
);
});
scope.spawn(move |_| {
thread::sleep(ms(1500));
assert_eq!(r.recv(), Ok(8));
});
})
.unwrap();
}
#[test]
fn len() {
const COUNT: usize = 25_000;
let (s, r) = bounded(0);
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
scope(|scope| {
scope.spawn(|_| {
for i in 0..COUNT {
assert_eq!(r.recv(), Ok(i));
assert_eq!(r.len(), 0);
}
});
scope.spawn(|_| {
for i in 0..COUNT {
s.send(i).unwrap();
assert_eq!(s.len(), 0);
}
});
})
.unwrap();
assert_eq!(s.len(), 0);
assert_eq!(r.len(), 0);
}
#[test]
fn disconnect_wakes_sender() {
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
assert_eq!(s.send(()), Err(SendError(())));
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
drop(r);
});
})
.unwrap();
}
#[test]
fn disconnect_wakes_receiver() {
let (s, r) = bounded::<()>(0);
scope(|scope| {
scope.spawn(move |_| {
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
thread::sleep(ms(1000));
drop(s);
});
})
.unwrap();
}
#[test]
fn spsc() {
const COUNT: usize = 100_000;
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
for i in 0..COUNT {
assert_eq!(r.recv(), Ok(i));
}
assert!(r.recv().is_err());
});
scope.spawn(move |_| {
for i in 0..COUNT {
s.send(i).unwrap();
}
});
})
.unwrap();
}
#[test]
fn mpmc() {
const COUNT: usize = 25_000;
const THREADS: usize = 4;
let (s, r) = bounded::<usize>(0);
let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();
scope(|scope| {
for _ in 0..THREADS {
scope.spawn(|_| {
for _ in 0..COUNT {
let n = r.recv().unwrap();
v[n].fetch_add(1, Ordering::SeqCst);
}
});
}
for _ in 0..THREADS {
scope.spawn(|_| {
for i in 0..COUNT {
s.send(i).unwrap();
}
});
}
})
.unwrap();
for c in v {
assert_eq!(c.load(Ordering::SeqCst), THREADS);
}
}
#[test]
fn stress_oneshot() {
const COUNT: usize = 10_000;
for _ in 0..COUNT {
let (s, r) = bounded(1);
scope(|scope| {
scope.spawn(|_| r.recv().unwrap());
scope.spawn(|_| s.send(0).unwrap());
})
.unwrap();
}
}
#[test]
fn stress_iter() {
const COUNT: usize = 1000;
let (request_s, request_r) = bounded(0);
let (response_s, response_r) = bounded(0);
scope(|scope| {
scope.spawn(move |_| {
let mut count = 0;
loop {
for x in response_r.try_iter() {
count += x;
if count == COUNT {
return;
}
}
let _ = request_s.try_send(());
}
});
for _ in request_r.iter() {
if response_s.send(1).is_err() {
break;
}
}
})
.unwrap();
}
#[test]
fn stress_timeout_two_threads() {
const COUNT: usize = 100;
let (s, r) = bounded(0);
scope(|scope| {
scope.spawn(|_| {
for i in 0..COUNT {
if i % 2 == 0 {
thread::sleep(ms(50));
}
loop {
if let Ok(()) = s.send_timeout(i, ms(10)) {
break;
}
}
}
});
scope.spawn(|_| {
for i in 0..COUNT {
if i % 2 == 0 {
thread::sleep(ms(50));
}
loop {
if let Ok(x) = r.recv_timeout(ms(10)) {
assert_eq!(x, i);
break;
}
}
}
});
})
.unwrap();
}
#[test]
fn drops() {
static DROPS: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, PartialEq)]
struct DropCounter;
impl Drop for DropCounter {
fn drop(&mut self) {
DROPS.fetch_add(1, Ordering::SeqCst);
}
}
let mut rng = thread_rng();
for _ in 0..100 {
let steps = rng.gen_range(0..3_000);
DROPS.store(0, Ordering::SeqCst);
let (s, r) = bounded::<DropCounter>(0);
scope(|scope| {
scope.spawn(|_| {
for _ in 0..steps {
r.recv().unwrap();
}
});
scope.spawn(|_| {
for _ in 0..steps {
s.send(DropCounter).unwrap();
}
});
})
.unwrap();
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
drop(s);
drop(r);
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
}
}
// #[test]
// fn fairness() {
// const COUNT: usize = 10_000;
// let (s1, r1) = bounded::<()>(0);
// let (s2, r2) = bounded::<()>(0);
// scope(|scope| {
// scope.spawn(|_| {
// let mut hits = [0usize; 2];
// for _ in 0..COUNT {
// select! {
// recv(r1) -> _ => hits[0] += 1,
// recv(r2) -> _ => hits[1] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// });
// let mut hits = [0usize; 2];
// for _ in 0..COUNT {
// select! {
// send(s1, ()) -> _ => hits[0] += 1,
// send(s2, ()) -> _ => hits[1] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// })
// .unwrap();
// }
// #[test]
// fn fairness_duplicates() {
// const COUNT: usize = 10_000;
// let (s, r) = bounded::<()>(0);
// scope(|scope| {
// scope.spawn(|_| {
// let mut hits = [0usize; 5];
// for _ in 0..COUNT {
// select! {
// recv(r) -> _ => hits[0] += 1,
// recv(r) -> _ => hits[1] += 1,
// recv(r) -> _ => hits[2] += 1,
// recv(r) -> _ => hits[3] += 1,
// recv(r) -> _ => hits[4] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// });
// let mut hits = [0usize; 5];
// for _ in 0..COUNT {
// select! {
// send(s, ()) -> _ => hits[0] += 1,
// send(s, ()) -> _ => hits[1] += 1,
// send(s, ()) -> _ => hits[2] += 1,
// send(s, ()) -> _ => hits[3] += 1,
// send(s, ()) -> _ => hits[4] += 1,
// }
// }
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
// })
// .unwrap();
// }
// #[test]
// fn recv_in_send() {
// let (s, r) = bounded(0);
// scope(|scope| {
// scope.spawn(|_| {
// thread::sleep(ms(100));
// r.recv()
// });
// scope.spawn(|_| {
// thread::sleep(ms(500));
// s.send(()).unwrap();
// });
// select! {
// send(s, r.recv().unwrap()) -> _ => {}
// }
// })
// .unwrap();
// }
#[test]
fn channel_through_channel() {
const COUNT: usize = 1000;
type T = Box<dyn Any + Send>;
let (s, r) = bounded::<T>(0);
scope(|scope| {
scope.spawn(move |_| {
let mut s = s;
for _ in 0..COUNT {
let (new_s, new_r) = bounded(0);
let new_r: T = Box::new(Some(new_r));
s.send(new_r).unwrap();
s = new_s;
}
});
scope.spawn(move |_| {
let mut r = r;
for _ in 0..COUNT {
r = r
.recv()
.unwrap()
.downcast_mut::<Option<Receiver<T>>>()
.unwrap()
.take()
.unwrap()
}
});
})
.unwrap();
}