зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1785002 - Update crossbeam-deque to 0.8.2. r=emilio,supply-chain-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D154720
This commit is contained in:
Родитель
e6ec815843
Коммит
b6ab763ae0
|
@ -990,9 +990,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
||||
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-epoch 0.9.8",
|
||||
|
@ -4347,7 +4347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque 0.8.1",
|
||||
"crossbeam-deque 0.8.2",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
@ -4359,7 +4359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque 0.8.1",
|
||||
"crossbeam-deque 0.8.2",
|
||||
"crossbeam-utils 0.8.8",
|
||||
"num_cpus",
|
||||
]
|
||||
|
|
|
@ -132,6 +132,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
|
|||
criteria = "safe-to-deploy"
|
||||
delta = "0.5.4 -> 0.5.6"
|
||||
|
||||
[[audits.crossbeam-deque]]
|
||||
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.8.1 -> 0.8.2"
|
||||
|
||||
[[audits.cstr]]
|
||||
who = "Emilio Cobos Álvarez <emilio@crisal.io>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"CHANGELOG.md":"7d5f333652da0da5f068ff91ecf259599f9ff4a4448bd987dd451699b66f0f59","Cargo.toml":"a9a138b4e005ddea76f588ca7004629ebd8f1a64cd1d55474fe36cae4c57a890","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"6b0a911f542186ef96eb56537cade0ecf1a5731d5d494b7094ff87f0fdeb7710","src/deque.rs":"64a2153dc566847fd9fa0e6b2b7adb3933af9984fbe3429b6f1200b058bb9850","src/lib.rs":"9f0581481691bc698176f369410726adf597d470b9d14e226a65f490d6aff8c6","tests/fifo.rs":"1d83f9ffeeba2cd6bd32f1ab136d843b8c73075d5045619be12dc3c27d8ab3ba","tests/injector.rs":"6812c97615e3f685b5612c390861f2e570ff469f3b9871ba97ddbed5c1f5266b","tests/lifo.rs":"b2ddc8154492322e734b23f35ce54040f9ec84ef878009de3a64d44d35c365a6","tests/steal.rs":"cdf588cc13eeb275ef1231eb18e3245faca7a2d054fa6527bfdba2a34bc8f7bf"},"package":"6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"}
|
||||
{"files":{"CHANGELOG.md":"ad5f2c10299e57aaed2d1b8f8a109faa2dfb16c52ce81f60ec5adb0ea9308d7f","Cargo.toml":"4802e7c0d5ab1dc35c162671483a6ee9bff5a3f1d6dd620a01863ac25068019e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"3c62aa0ee37cf714b5b3c304545d5caea4cc0a71020fccb1f146611d64202bb2","src/deque.rs":"cfb3c5b3bcea1f27ca2633d8b8576ff2080e1e9fc083236f2db7916bb77786ed","src/lib.rs":"ec0257a388627d691d652fd04d261c5c0590e1e31a35c8bf5912afac51fd5734","tests/fifo.rs":"3d98e0d4ca7cfddf10708b71642cf1ff05543d067ad837e48401d63cc31c0a18","tests/injector.rs":"fb054ef9fcac5f12e08b7b3451f370b96ab7589d32ef5c02e25958a473c45519","tests/lifo.rs":"57abdb3fc5920a422f785ba308b658bdc5400947532eeffb799f2395a2061549","tests/steal.rs":"cdf588cc13eeb275ef1231eb18e3245faca7a2d054fa6527bfdba2a34bc8f7bf"},"package":"715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"}
|
|
@ -1,3 +1,7 @@
|
|||
# Version 0.8.2
|
||||
|
||||
- Bump the minimum supported Rust version to 1.38. (#877)
|
||||
|
||||
# Version 0.8.1
|
||||
|
||||
- Fix deque steal race condition. (#726)
|
||||
|
@ -5,26 +9,40 @@
|
|||
|
||||
# Version 0.8.0
|
||||
|
||||
**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details.
|
||||
|
||||
- Bump the minimum supported Rust version to 1.36.
|
||||
- Add `Worker::len()` and `Injector::len()` methods.
|
||||
- Add `std` (enabled by default) feature for forward compatibility.
|
||||
|
||||
# Version 0.7.4
|
||||
|
||||
- Fix deque steal race condition.
|
||||
|
||||
# Version 0.7.3
|
||||
|
||||
**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details.
|
||||
|
||||
- Stop stealing from the same deque. (#448)
|
||||
- Fix unsoundness issues by adopting `MaybeUninit`. (#458)
|
||||
|
||||
# Version 0.7.2
|
||||
|
||||
**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details.
|
||||
|
||||
- Bump `crossbeam-epoch` to `0.8`.
|
||||
- Bump `crossbeam-utils` to `0.7`.
|
||||
|
||||
# Version 0.7.1
|
||||
|
||||
**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details.
|
||||
|
||||
- Bump the minimum required version of `crossbeam-utils`.
|
||||
|
||||
# Version 0.7.0
|
||||
|
||||
**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details.
|
||||
|
||||
- Make `Worker::pop()` faster in the FIFO case.
|
||||
- Replace `fifo()` nad `lifo()` with `Worker::new_fifo()` and `Worker::new_lifo()`.
|
||||
- Add more batched steal methods.
|
||||
|
|
|
@ -11,16 +11,26 @@
|
|||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.38"
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.1"
|
||||
authors = ["The Crossbeam Project Developers"]
|
||||
version = "0.8.2"
|
||||
description = "Concurrent work-stealing deque"
|
||||
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque"
|
||||
documentation = "https://docs.rs/crossbeam-deque"
|
||||
keywords = ["chase-lev", "lock-free", "scheduler", "scheduling"]
|
||||
categories = ["algorithms", "concurrency", "data-structures"]
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"chase-lev",
|
||||
"lock-free",
|
||||
"scheduler",
|
||||
"scheduling",
|
||||
]
|
||||
categories = [
|
||||
"algorithms",
|
||||
"concurrency",
|
||||
"data-structures",
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/crossbeam-rs/crossbeam"
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "1"
|
||||
|
||||
|
@ -33,9 +43,13 @@ default-features = false
|
|||
version = "0.8"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.8"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["crossbeam-epoch/std", "crossbeam-utils/std"]
|
||||
std = [
|
||||
"crossbeam-epoch/std",
|
||||
"crossbeam-utils/std",
|
||||
]
|
||||
|
|
|
@ -8,7 +8,7 @@ https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque#license)
|
|||
https://crates.io/crates/crossbeam-deque)
|
||||
[![Documentation](https://docs.rs/crossbeam-deque/badge.svg)](
|
||||
https://docs.rs/crossbeam-deque)
|
||||
[![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-lightgray.svg)](
|
||||
[![Rust 1.38+](https://img.shields.io/badge/rust-1.38+-lightgray.svg)](
|
||||
https://www.rust-lang.org)
|
||||
[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ)
|
||||
|
||||
|
@ -28,7 +28,7 @@ crossbeam-deque = "0.8"
|
|||
|
||||
Crossbeam Deque supports stable Rust releases going back at least six months,
|
||||
and every time the minimum supported Rust version is increased, a new minor
|
||||
version is released. Currently, the minimum supported Rust version is 1.36.
|
||||
version is released. Currently, the minimum supported Rust version is 1.38.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::cmp;
|
|||
use std::fmt;
|
||||
use std::iter::FromIterator;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::mem::{self, ManuallyDrop, MaybeUninit};
|
||||
use std::ptr;
|
||||
use std::sync::atomic::{self, AtomicIsize, AtomicPtr, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
@ -38,9 +38,8 @@ impl<T> Buffer<T> {
|
|||
fn alloc(cap: usize) -> Buffer<T> {
|
||||
debug_assert_eq!(cap, cap.next_power_of_two());
|
||||
|
||||
let mut v = Vec::with_capacity(cap);
|
||||
let mut v = ManuallyDrop::new(Vec::with_capacity(cap));
|
||||
let ptr = v.as_mut_ptr();
|
||||
mem::forget(v);
|
||||
|
||||
Buffer { ptr, cap }
|
||||
}
|
||||
|
@ -53,6 +52,8 @@ impl<T> Buffer<T> {
|
|||
/// Returns a pointer to the task at the specified `index`.
|
||||
unsafe fn at(&self, index: isize) -> *mut T {
|
||||
// `self.cap` is always a power of two.
|
||||
// We do all the loads at `MaybeUninit` because we might realize, after loading, that we
|
||||
// don't actually have the right to access this memory.
|
||||
self.ptr.offset(index & (self.cap - 1) as isize)
|
||||
}
|
||||
|
||||
|
@ -62,8 +63,8 @@ impl<T> Buffer<T> {
|
|||
/// technically speaking a data race and therefore UB. We should use an atomic store here, but
|
||||
/// that would be more expensive and difficult to implement generically for all types `T`.
|
||||
/// Hence, as a hack, we use a volatile write instead.
|
||||
unsafe fn write(&self, index: isize, task: T) {
|
||||
ptr::write_volatile(self.at(index), task)
|
||||
unsafe fn write(&self, index: isize, task: MaybeUninit<T>) {
|
||||
ptr::write_volatile(self.at(index).cast::<MaybeUninit<T>>(), task)
|
||||
}
|
||||
|
||||
/// Reads a task from the specified `index`.
|
||||
|
@ -71,9 +72,9 @@ impl<T> Buffer<T> {
|
|||
/// This method might be concurrently called with another `write` at the same index, which is
|
||||
/// technically speaking a data race and therefore UB. We should use an atomic load here, but
|
||||
/// that would be more expensive and difficult to implement generically for all types `T`.
|
||||
/// Hence, as a hack, we use a volatile write instead.
|
||||
unsafe fn read(&self, index: isize) -> T {
|
||||
ptr::read_volatile(self.at(index))
|
||||
/// Hence, as a hack, we use a volatile load instead.
|
||||
unsafe fn read(&self, index: isize) -> MaybeUninit<T> {
|
||||
ptr::read_volatile(self.at(index).cast::<MaybeUninit<T>>())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,8 +116,8 @@ struct Inner<T> {
|
|||
impl<T> Drop for Inner<T> {
|
||||
fn drop(&mut self) {
|
||||
// Load the back index, front index, and buffer.
|
||||
let b = self.back.load(Ordering::Relaxed);
|
||||
let f = self.front.load(Ordering::Relaxed);
|
||||
let b = *self.back.get_mut();
|
||||
let f = *self.front.get_mut();
|
||||
|
||||
unsafe {
|
||||
let buffer = self.buffer.load(Ordering::Relaxed, epoch::unprotected());
|
||||
|
@ -406,7 +407,7 @@ impl<T> Worker<T> {
|
|||
|
||||
// Write `task` into the slot.
|
||||
unsafe {
|
||||
buffer.write(b, task);
|
||||
buffer.write(b, MaybeUninit::new(task));
|
||||
}
|
||||
|
||||
atomic::fence(Ordering::Release);
|
||||
|
@ -461,7 +462,7 @@ impl<T> Worker<T> {
|
|||
unsafe {
|
||||
// Read the popped task.
|
||||
let buffer = self.buffer.get();
|
||||
let task = buffer.read(f);
|
||||
let task = buffer.read(f).assume_init();
|
||||
|
||||
// Shrink the buffer if `len - 1` is less than one fourth of the capacity.
|
||||
if buffer.cap > MIN_CAP && len <= buffer.cap as isize / 4 {
|
||||
|
@ -509,8 +510,8 @@ impl<T> Worker<T> {
|
|||
)
|
||||
.is_err()
|
||||
{
|
||||
// Failed. We didn't pop anything.
|
||||
mem::forget(task.take());
|
||||
// Failed. We didn't pop anything. Reset to `None`.
|
||||
task.take();
|
||||
}
|
||||
|
||||
// Restore the back index to the original task.
|
||||
|
@ -524,7 +525,7 @@ impl<T> Worker<T> {
|
|||
}
|
||||
}
|
||||
|
||||
task
|
||||
task.map(|t| unsafe { t.assume_init() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -661,12 +662,11 @@ impl<T> Stealer<T> {
|
|||
.is_err()
|
||||
{
|
||||
// We didn't steal this task, forget it.
|
||||
mem::forget(task);
|
||||
return Steal::Retry;
|
||||
}
|
||||
|
||||
// Return the stolen task.
|
||||
Steal::Success(task)
|
||||
Steal::Success(unsafe { task.assume_init() })
|
||||
}
|
||||
|
||||
/// Steals a batch of tasks and pushes them into another worker.
|
||||
|
@ -821,7 +821,6 @@ impl<T> Stealer<T> {
|
|||
.is_err()
|
||||
{
|
||||
// We didn't steal this task, forget it and break from the loop.
|
||||
mem::forget(task);
|
||||
batch_size = i;
|
||||
break;
|
||||
}
|
||||
|
@ -975,7 +974,6 @@ impl<T> Stealer<T> {
|
|||
.is_err()
|
||||
{
|
||||
// We didn't steal this task, forget it.
|
||||
mem::forget(task);
|
||||
return Steal::Retry;
|
||||
}
|
||||
|
||||
|
@ -992,7 +990,6 @@ impl<T> Stealer<T> {
|
|||
.is_err()
|
||||
{
|
||||
// We didn't steal this task, forget it.
|
||||
mem::forget(task);
|
||||
return Steal::Retry;
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1034,6 @@ impl<T> Stealer<T> {
|
|||
.is_err()
|
||||
{
|
||||
// We didn't steal this task, forget it and break from the loop.
|
||||
mem::forget(tmp);
|
||||
batch_size = i;
|
||||
break;
|
||||
}
|
||||
|
@ -1077,7 +1073,7 @@ impl<T> Stealer<T> {
|
|||
dest.inner.back.store(dest_b, Ordering::Release);
|
||||
|
||||
// Return with success.
|
||||
Steal::Success(task)
|
||||
Steal::Success(unsafe { task.assume_init() })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,6 +1119,11 @@ struct Slot<T> {
|
|||
}
|
||||
|
||||
impl<T> Slot<T> {
|
||||
const UNINIT: Self = Self {
|
||||
task: UnsafeCell::new(MaybeUninit::uninit()),
|
||||
state: AtomicUsize::new(0),
|
||||
};
|
||||
|
||||
/// Waits until a task is written into the slot.
|
||||
fn wait_write(&self) {
|
||||
let backoff = Backoff::new();
|
||||
|
@ -1146,13 +1147,10 @@ struct Block<T> {
|
|||
impl<T> Block<T> {
|
||||
/// Creates an empty block that starts at `start_index`.
|
||||
fn new() -> Block<T> {
|
||||
// SAFETY: This is safe because:
|
||||
// [1] `Block::next` (AtomicPtr) may be safely zero initialized.
|
||||
// [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4].
|
||||
// [3] `Slot::task` (UnsafeCell) may be safely zero initialized because it
|
||||
// holds a MaybeUninit.
|
||||
// [4] `Slot::state` (AtomicUsize) may be safely zero initialized.
|
||||
unsafe { MaybeUninit::zeroed().assume_init() }
|
||||
Self {
|
||||
next: AtomicPtr::new(ptr::null_mut()),
|
||||
slots: [Slot::UNINIT; BLOCK_CAP],
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits until the next pointer is set.
|
||||
|
@ -1535,7 +1533,7 @@ impl<T> Injector<T> {
|
|||
// Read the task.
|
||||
let slot = (*block).slots.get_unchecked(offset + i);
|
||||
slot.wait_write();
|
||||
let task = slot.task.get().read().assume_init();
|
||||
let task = slot.task.get().read();
|
||||
|
||||
// Write it into the destination queue.
|
||||
dest_buffer.write(dest_b.wrapping_add(i as isize), task);
|
||||
|
@ -1547,7 +1545,7 @@ impl<T> Injector<T> {
|
|||
// Read the task.
|
||||
let slot = (*block).slots.get_unchecked(offset + i);
|
||||
slot.wait_write();
|
||||
let task = slot.task.get().read().assume_init();
|
||||
let task = slot.task.get().read();
|
||||
|
||||
// Write it into the destination queue.
|
||||
dest_buffer.write(dest_b.wrapping_add((batch_size - 1 - i) as isize), task);
|
||||
|
@ -1689,7 +1687,7 @@ impl<T> Injector<T> {
|
|||
// Read the task.
|
||||
let slot = (*block).slots.get_unchecked(offset);
|
||||
slot.wait_write();
|
||||
let task = slot.task.get().read().assume_init();
|
||||
let task = slot.task.get().read();
|
||||
|
||||
match dest.flavor {
|
||||
Flavor::Fifo => {
|
||||
|
@ -1698,7 +1696,7 @@ impl<T> Injector<T> {
|
|||
// Read the task.
|
||||
let slot = (*block).slots.get_unchecked(offset + i + 1);
|
||||
slot.wait_write();
|
||||
let task = slot.task.get().read().assume_init();
|
||||
let task = slot.task.get().read();
|
||||
|
||||
// Write it into the destination queue.
|
||||
dest_buffer.write(dest_b.wrapping_add(i as isize), task);
|
||||
|
@ -1711,7 +1709,7 @@ impl<T> Injector<T> {
|
|||
// Read the task.
|
||||
let slot = (*block).slots.get_unchecked(offset + i + 1);
|
||||
slot.wait_write();
|
||||
let task = slot.task.get().read().assume_init();
|
||||
let task = slot.task.get().read();
|
||||
|
||||
// Write it into the destination queue.
|
||||
dest_buffer.write(dest_b.wrapping_add((batch_size - 1 - i) as isize), task);
|
||||
|
@ -1744,7 +1742,7 @@ impl<T> Injector<T> {
|
|||
}
|
||||
}
|
||||
|
||||
Steal::Success(task)
|
||||
Steal::Success(task.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1820,9 +1818,9 @@ impl<T> Injector<T> {
|
|||
|
||||
impl<T> Drop for Injector<T> {
|
||||
fn drop(&mut self) {
|
||||
let mut head = self.head.index.load(Ordering::Relaxed);
|
||||
let mut tail = self.tail.index.load(Ordering::Relaxed);
|
||||
let mut block = self.head.block.load(Ordering::Relaxed);
|
||||
let mut head = *self.head.index.get_mut();
|
||||
let mut tail = *self.tail.index.get_mut();
|
||||
let mut block = *self.head.block.get_mut();
|
||||
|
||||
// Erase the lower bits.
|
||||
head &= !((1 << SHIFT) - 1);
|
||||
|
@ -1840,7 +1838,7 @@ impl<T> Drop for Injector<T> {
|
|||
p.as_mut_ptr().drop_in_place();
|
||||
} else {
|
||||
// Deallocate the block and move to the next one.
|
||||
let next = (*block).next.load(Ordering::Relaxed);
|
||||
let next = *(*block).next.get_mut();
|
||||
drop(Box::from_raw(block));
|
||||
block = next;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
rust_2018_idioms,
|
||||
unreachable_pub
|
||||
)]
|
||||
#![allow(clippy::question_mark)] // https://github.com/rust-lang/rust-clippy/issues/8281
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
|
|
@ -71,6 +71,9 @@ fn is_empty() {
|
|||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 50_000;
|
||||
|
||||
let w = Worker::new_fifo();
|
||||
|
@ -100,6 +103,9 @@ fn spsc() {
|
|||
#[test]
|
||||
fn stampede() {
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
|
||||
let w = Worker::new_fifo();
|
||||
|
@ -141,6 +147,9 @@ fn stampede() {
|
|||
#[test]
|
||||
fn stress() {
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
|
||||
let w = Worker::new_fifo();
|
||||
|
@ -197,6 +206,7 @@ fn stress() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg_attr(miri, ignore)] // Miri is too slow
|
||||
#[test]
|
||||
fn no_starvation() {
|
||||
const THREADS: usize = 8;
|
||||
|
@ -258,8 +268,17 @@ fn no_starvation() {
|
|||
|
||||
#[test]
|
||||
fn destructors() {
|
||||
#[cfg(miri)]
|
||||
const THREADS: usize = 2;
|
||||
#[cfg(not(miri))]
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 1000;
|
||||
|
||||
struct Elem(usize, Arc<Mutex<Vec<usize>>>);
|
||||
|
@ -330,7 +349,7 @@ fn destructors() {
|
|||
{
|
||||
let mut v = dropped.lock().unwrap();
|
||||
assert_eq!(v.len(), rem);
|
||||
v.sort();
|
||||
v.sort_unstable();
|
||||
for pair in v.windows(2) {
|
||||
assert_eq!(pair[0] + 1, pair[1]);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ fn is_empty() {
|
|||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 100_000;
|
||||
|
||||
let q = Injector::new();
|
||||
|
@ -58,6 +61,8 @@ fn spsc() {
|
|||
assert_eq!(i, v);
|
||||
break;
|
||||
}
|
||||
#[cfg(miri)]
|
||||
std::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,6 +78,9 @@ fn spsc() {
|
|||
|
||||
#[test]
|
||||
fn mpmc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 25_000;
|
||||
const THREADS: usize = 4;
|
||||
|
||||
|
@ -96,6 +104,8 @@ fn mpmc() {
|
|||
v[n].fetch_add(1, SeqCst);
|
||||
break;
|
||||
}
|
||||
#[cfg(miri)]
|
||||
std::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -111,6 +121,9 @@ fn mpmc() {
|
|||
#[test]
|
||||
fn stampede() {
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
|
||||
let q = Injector::new();
|
||||
|
@ -152,6 +165,9 @@ fn stampede() {
|
|||
#[test]
|
||||
fn stress() {
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
|
||||
let q = Injector::new();
|
||||
|
@ -208,6 +224,7 @@ fn stress() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg_attr(miri, ignore)] // Miri is too slow
|
||||
#[test]
|
||||
fn no_starvation() {
|
||||
const THREADS: usize = 8;
|
||||
|
@ -269,8 +286,17 @@ fn no_starvation() {
|
|||
|
||||
#[test]
|
||||
fn destructors() {
|
||||
#[cfg(miri)]
|
||||
const THREADS: usize = 2;
|
||||
#[cfg(not(miri))]
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 1000;
|
||||
|
||||
struct Elem(usize, Arc<Mutex<Vec<usize>>>);
|
||||
|
@ -341,7 +367,7 @@ fn destructors() {
|
|||
{
|
||||
let mut v = dropped.lock().unwrap();
|
||||
assert_eq!(v.len(), rem);
|
||||
v.sort();
|
||||
v.sort_unstable();
|
||||
for pair in v.windows(2) {
|
||||
assert_eq!(pair[0] + 1, pair[1]);
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ fn is_empty() {
|
|||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 50_000;
|
||||
|
||||
let w = Worker::new_lifo();
|
||||
|
@ -84,6 +87,8 @@ fn spsc() {
|
|||
assert_eq!(i, v);
|
||||
break;
|
||||
}
|
||||
#[cfg(miri)]
|
||||
std::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +105,9 @@ fn spsc() {
|
|||
#[test]
|
||||
fn stampede() {
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
|
||||
let w = Worker::new_lifo();
|
||||
|
@ -141,6 +149,9 @@ fn stampede() {
|
|||
#[test]
|
||||
fn stress() {
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
|
||||
let w = Worker::new_lifo();
|
||||
|
@ -197,6 +208,7 @@ fn stress() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg_attr(miri, ignore)] // Miri is too slow
|
||||
#[test]
|
||||
fn no_starvation() {
|
||||
const THREADS: usize = 8;
|
||||
|
@ -258,8 +270,17 @@ fn no_starvation() {
|
|||
|
||||
#[test]
|
||||
fn destructors() {
|
||||
#[cfg(miri)]
|
||||
const THREADS: usize = 2;
|
||||
#[cfg(not(miri))]
|
||||
const THREADS: usize = 8;
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 500;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 50_000;
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 1000;
|
||||
|
||||
struct Elem(usize, Arc<Mutex<Vec<usize>>>);
|
||||
|
@ -330,7 +351,7 @@ fn destructors() {
|
|||
{
|
||||
let mut v = dropped.lock().unwrap();
|
||||
assert_eq!(v.len(), rem);
|
||||
v.sort();
|
||||
v.sort_unstable();
|
||||
for pair in v.windows(2) {
|
||||
assert_eq!(pair[0] + 1, pair[1]);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче