diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /vendor/rayon | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
69 files changed, 1730 insertions, 802 deletions
diff --git a/vendor/rayon-core/.cargo-checksum.json b/vendor/rayon-core/.cargo-checksum.json index 9a10e07bc..701513eed 100644 --- a/vendor/rayon-core/.cargo-checksum.json +++ b/vendor/rayon-core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"aae8e7b3c8418428ed6a659ffd89148ad1ce0df0f7d8ebdb4b58d9ebd4377bb8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"27837a5d829f46e889bf9a4a8dff964709c8a3cfc0a24bc4f0ef1e9034798b41","build.rs":"fa31cb198b772600d100a7c403ddedccef637d2e6b2da431fa7f02ca41307fc6","src/compile_fail/mod.rs":"4d70256295bd64691a8c1994b323559cda1888e85f0b45ca55711541c257dcb6","src/compile_fail/quicksort_race1.rs":"35f498cda38f4eb6e00117f78ed68e0fe5a3fa61c25303d9c08a19bda345bc6c","src/compile_fail/quicksort_race2.rs":"cbb40030c7867cae34bb373b6ec5d97c2ac6de39bc917f47879b30eb423924bc","src/compile_fail/quicksort_race3.rs":"8403643e64c969306b1a9b1243378e6ccdd313b57e1878dbd31393618082fd35","src/compile_fail/rc_return.rs":"b6f1f821ef30086e2990db1ac58a92adaf31e57c23c587c7746d6303865c5c0f","src/compile_fail/rc_upvar.rs":"92a799b313fb88a0eb83fc1aaaea4b61604222b45e20f1c22ff5b092a03f8620","src/compile_fail/scope_join_bad.rs":"892959949f77cadfc07458473e7a290301182027ca64428df5a8ce887be0892b","src/job.rs":"f6b439551ea723f8657be9971ce5f42660e1a2bb743e226e3255887056770264","src/join/mod.rs":"91f58385a3fc5a62187df32338595a479df5aee08f8af08e5066dbc2488bacf4","src/join/test.rs":"71e9a5fda81610d0a41004ccdc24dfd1b1ebe3f1f87d2ddf730c48e69659a234","src/latch.rs":"d32eb2caa0b4c5218152d85eebaf3c7013cc5ce542e4e1f087da1e755402582e","src/lib.rs":"946d07c9fd32211cc1d98ed67c6c8ff3a947736d6b110e8511aabf1b8c9bb185","src/log.rs":"8a25ed8661f5ae3317085a108f78bb5f5a2e40827dbde9b16d6b8a560a5f2c39","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/registry.rs":"8bf999e126af3ec0638e3e137211f7b4cfb2e3441dfd121d43266f424394f380","src/scope/mod.rs":"f94cecc7b19e06db12ea6e243a03e8913c41f08a3f9711bb1a5f323459ee4346","src/scope/test.rs":"34fb0af1286bd2bcc2f7cd03e2f0d35b3d2284074ce6829ba1c319bae83eb5bf","src/sleep/README.md":"4714cd03a8c2be7648b5f48d85b121cc3bc39af6b65c025bfa34640d85af18d6","src/sleep/counters.rs":"3488d3af9711db78697a42822a87b218aaf80f1c2a41abc50e61aacd47b72bd0","src/sleep/mod.rs":"1ee6f29cb6885fc394be010fbba1b9baa18afd63e25b682d3b67daef8a1f45c0","src/spawn/mod.rs":"68b8ece5793abba647754744d5e23cf5f716ac86062818e594c90d8cf33de04a","src/spawn/test.rs":"836f5a39f35e037164a48a5dfcba7f01abde431fbf49e52e8776256249944d21","src/test.rs":"68334fad0e8ae154097383c6df3c2658dc969e37c88d7a57298dae6c84c491be","src/thread_pool/mod.rs":"9d56d3fecc976cde90ad445a8aceabc82d02a641043a3b5d68bb724fde61e3d7","src/thread_pool/test.rs":"c56e70402295d748fba1f679752d1b434811f8d54c2514a6ffb6284373740690","src/unwind.rs":"7baa4511467d008b14856ea8de7ced92b9251c9df4854f69c81f7efc3cf0cd6c","tests/double_init_fail.rs":"f6f6e1b45bdba6ef8f18d1981e5356a6d5ef2f3bbecd0c8ce4341c126a3a6f1d","tests/init_zero_threads.rs":"57f66d1662f7782848d45942faa613a608188eb400943e4efa4c3ec3375e1dac","tests/scope_join.rs":"56f570c4b6a01704aacf93e7f17f89fe0f40f46ed6f9ede517abfe9adaf91f83","tests/scoped_threadpool.rs":"0f6475f440a57b6f91ecdd720228395f4feaa6165b136558f65267e185fd7127","tests/simple_panic.rs":"916d40d36c1a0fad3e1dfb31550f0672641feab4b03d480f039143dbe2f2445f","tests/stack_overflow_crash.rs":"e8865d33d51a58f5c6639f457d91f82f2a4379cf5129094eaa521e95bad72d51"},"package":"258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"}
\ No newline at end of file +{"files":{"Cargo.toml":"26cd5b9b16759a466399717efce4be4e6dffa34755eedf1e9f4bee1e9fd191e7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"53c557d462dbc66104f80bf86bb7e47dbc07b92eceec9bf450538ba70c0a4d83","build.rs":"fa31cb198b772600d100a7c403ddedccef637d2e6b2da431fa7f02ca41307fc6","src/broadcast/mod.rs":"c61a4a47aa42255fb7489db8abc7ee28cc17a2122932d2b71c1177d732351111","src/broadcast/test.rs":"519ee1bf9f043fcc93904b5ddf379e089b956eae4cb2261a5a0bd2413aa0eb97","src/compile_fail/mod.rs":"4d70256295bd64691a8c1994b323559cda1888e85f0b45ca55711541c257dcb6","src/compile_fail/quicksort_race1.rs":"35f498cda38f4eb6e00117f78ed68e0fe5a3fa61c25303d9c08a19bda345bc6c","src/compile_fail/quicksort_race2.rs":"cbb40030c7867cae34bb373b6ec5d97c2ac6de39bc917f47879b30eb423924bc","src/compile_fail/quicksort_race3.rs":"8403643e64c969306b1a9b1243378e6ccdd313b57e1878dbd31393618082fd35","src/compile_fail/rc_return.rs":"197894803d8df58fc8005d90c86b90cd98f1972f1a4b57438516a565df35903f","src/compile_fail/rc_upvar.rs":"42d110429621f407ef0dada1306dab116583d2c782a99894204dd8e0ccd2312f","src/compile_fail/scope_join_bad.rs":"892959949f77cadfc07458473e7a290301182027ca64428df5a8ce887be0892b","src/job.rs":"f48cb1984f5bdfff5eca4559381b815689b7343b4da5e5fb46106c1888dff275","src/join/mod.rs":"91f58385a3fc5a62187df32338595a479df5aee08f8af08e5066dbc2488bacf4","src/join/test.rs":"71e9a5fda81610d0a41004ccdc24dfd1b1ebe3f1f87d2ddf730c48e69659a234","src/latch.rs":"7dfa6cb761420b10ebcb42f8dc5bfc04b8921b740ef7adc6e53de838a7a527dd","src/lib.rs":"840c43778294cfb1783d3aad09b68bcdf327412b2c16d05c0000a07c7dc0855a","src/log.rs":"3f901d61125584a50b05892b7e690872bda15be2150b9c0595c6125664f4cf3e","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/registry.rs":"dfc8980dfb44778fe54632e8fbbb29a4ca5cef1da0cb768194a1df320e168fc2","src/scope/mod.rs":"abe5158c401fccdd4d488386197d369464d467297e231931a05cc3c85046583b","src/scope/test.rs":"8ce83ef72481092bff22c92c3defd349cd3376cccbfef3a686ea8df802858ae5","src/sleep/README.md":"e1ac1a5556cf257f38b7654feb0615c208d9186fefbe52a584d4fe6545d7c373","src/sleep/counters.rs":"2ce3052f05b3b75b1b96c6604fc0dfb6de867426981b37641410c068f92897bd","src/sleep/mod.rs":"94d36b5659657a0a4814228eb0538e41345de11b021e306382f14ebd501884ff","src/spawn/mod.rs":"9968c3e04d93de19b69f1f06af2b9be739a8d64fe4178275ac46614c8f254efe","src/spawn/test.rs":"836f5a39f35e037164a48a5dfcba7f01abde431fbf49e52e8776256249944d21","src/test.rs":"161498c8722a1f9e05ba7d107896453b660e0e72d9f701810721c2d27db26b9b","src/thread_pool/mod.rs":"904eecffd3b947a7dcdf19ed250abd999db1bfd21a15562f45f492f657c57a4f","src/thread_pool/test.rs":"188fc36abda2c63382ead1dbad01f56777de228f96b9b5d3b1fa98461e3b8045","src/unwind.rs":"7baa4511467d008b14856ea8de7ced92b9251c9df4854f69c81f7efc3cf0cd6c","tests/double_init_fail.rs":"30d9d4f80b426bdfc87b56e8e10511d4706d2f367ec310c7569bb35baf6862d2","tests/init_zero_threads.rs":"57f66d1662f7782848d45942faa613a608188eb400943e4efa4c3ec3375e1dac","tests/scope_join.rs":"56f570c4b6a01704aacf93e7f17f89fe0f40f46ed6f9ede517abfe9adaf91f83","tests/scoped_threadpool.rs":"0f6475f440a57b6f91ecdd720228395f4feaa6165b136558f65267e185fd7127","tests/simple_panic.rs":"916d40d36c1a0fad3e1dfb31550f0672641feab4b03d480f039143dbe2f2445f","tests/stack_overflow_crash.rs":"e8865d33d51a58f5c6639f457d91f82f2a4379cf5129094eaa521e95bad72d51"},"package":"cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"}
\ No newline at end of file diff --git a/vendor/rayon-core/Cargo.toml b/vendor/rayon-core/Cargo.toml index 051553c33..da520f775 100644 --- a/vendor/rayon-core/Cargo.toml +++ b/vendor/rayon-core/Cargo.toml @@ -10,9 +10,10 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" +rust-version = "1.56" name = "rayon-core" -version = "1.9.3" +version = "1.10.1" authors = [ "Niko Matsakis <niko@alum.mit.edu>", "Josh Stone <cuviper@gmail.com>", diff --git a/vendor/rayon-core/README.md b/vendor/rayon-core/README.md index 0c4936267..7bf2d9b1b 100644 --- a/vendor/rayon-core/README.md +++ b/vendor/rayon-core/README.md @@ -8,4 +8,4 @@ Please see [Rayon Docs] for details about using Rayon. [Rayon Docs]: https://docs.rs/rayon/ -Rayon-core currently requires `rustc 1.36.0` or greater. +Rayon-core currently requires `rustc 1.56.0` or greater. diff --git a/vendor/rayon-core/src/broadcast/mod.rs b/vendor/rayon-core/src/broadcast/mod.rs new file mode 100644 index 000000000..452aa71b6 --- /dev/null +++ b/vendor/rayon-core/src/broadcast/mod.rs @@ -0,0 +1,148 @@ +use crate::job::{ArcJob, StackJob}; +use crate::registry::{Registry, WorkerThread}; +use crate::scope::ScopeLatch; +use std::fmt; +use std::marker::PhantomData; +use std::sync::Arc; + +mod test; + +/// Executes `op` within every thread in the current threadpool. If this is +/// called from a non-Rayon thread, it will execute in the global threadpool. +/// Any attempts to use `join`, `scope`, or parallel iterators will then operate +/// within that threadpool. When the call has completed on each thread, returns +/// a vector containing all of their return values. +/// +/// For more information, see the [`ThreadPool::broadcast()`][m] method. +/// +/// [m]: struct.ThreadPool.html#method.broadcast +pub fn broadcast<OP, R>(op: OP) -> Vec<R> +where + OP: Fn(BroadcastContext<'_>) -> R + Sync, + R: Send, +{ + // We assert that current registry has not terminated. + unsafe { broadcast_in(op, &Registry::current()) } +} + +/// Spawns an asynchronous task on every thread in this thread-pool. This task +/// will run in the implicit, global scope, which means that it may outlast the +/// current stack frame -- therefore, it cannot capture any references onto the +/// stack (you will likely need a `move` closure). +/// +/// For more information, see the [`ThreadPool::spawn_broadcast()`][m] method. +/// +/// [m]: struct.ThreadPool.html#method.spawn_broadcast +pub fn spawn_broadcast<OP>(op: OP) +where + OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static, +{ + // We assert that current registry has not terminated. + unsafe { spawn_broadcast_in(op, &Registry::current()) } +} + +/// Provides context to a closure called by `broadcast`. +pub struct BroadcastContext<'a> { + worker: &'a WorkerThread, + + /// Make sure to prevent auto-traits like `Send` and `Sync`. + _marker: PhantomData<&'a mut dyn Fn()>, +} + +impl<'a> BroadcastContext<'a> { + pub(super) fn with<R>(f: impl FnOnce(BroadcastContext<'_>) -> R) -> R { + let worker_thread = WorkerThread::current(); + assert!(!worker_thread.is_null()); + f(BroadcastContext { + worker: unsafe { &*worker_thread }, + _marker: PhantomData, + }) + } + + /// Our index amongst the broadcast threads (ranges from `0..self.num_threads()`). + #[inline] + pub fn index(&self) -> usize { + self.worker.index() + } + + /// The number of threads receiving the broadcast in the thread pool. + /// + /// # Future compatibility note + /// + /// Future versions of Rayon might vary the number of threads over time, but + /// this method will always return the number of threads which are actually + /// receiving your particular `broadcast` call. + #[inline] + pub fn num_threads(&self) -> usize { + self.worker.registry().num_threads() + } +} + +impl<'a> fmt::Debug for BroadcastContext<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("BroadcastContext") + .field("index", &self.index()) + .field("num_threads", &self.num_threads()) + .field("pool_id", &self.worker.registry().id()) + .finish() + } +} + +/// Execute `op` on every thread in the pool. It will be executed on each +/// thread when they have nothing else to do locally, before they try to +/// steal work from other threads. This function will not return until all +/// threads have completed the `op`. +/// +/// Unsafe because `registry` must not yet have terminated. +pub(super) unsafe fn broadcast_in<OP, R>(op: OP, registry: &Arc<Registry>) -> Vec<R> +where + OP: Fn(BroadcastContext<'_>) -> R + Sync, + R: Send, +{ + let f = move |injected: bool| { + debug_assert!(injected); + BroadcastContext::with(&op) + }; + + let n_threads = registry.num_threads(); + let current_thread = WorkerThread::current().as_ref(); + let latch = ScopeLatch::with_count(n_threads, current_thread); + let jobs: Vec<_> = (0..n_threads).map(|_| StackJob::new(&f, &latch)).collect(); + let job_refs = jobs.iter().map(|job| job.as_job_ref()); + + registry.inject_broadcast(job_refs); + + // Wait for all jobs to complete, then collect the results, maybe propagating a panic. + latch.wait(current_thread); + jobs.into_iter().map(|job| job.into_result()).collect() +} + +/// Execute `op` on every thread in the pool. It will be executed on each +/// thread when they have nothing else to do locally, before they try to +/// steal work from other threads. This function returns immediately after +/// injecting the jobs. +/// +/// Unsafe because `registry` must not yet have terminated. +pub(super) unsafe fn spawn_broadcast_in<OP>(op: OP, registry: &Arc<Registry>) +where + OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static, +{ + let job = ArcJob::new({ + let registry = Arc::clone(registry); + move || { + registry.catch_unwind(|| BroadcastContext::with(&op)); + registry.terminate(); // (*) permit registry to terminate now + } + }); + + let n_threads = registry.num_threads(); + let job_refs = (0..n_threads).map(|_| { + // Ensure that registry cannot terminate until this job has executed + // on each thread. This ref is decremented at the (*) above. + registry.increment_terminate_count(); + + ArcJob::as_static_job_ref(&job) + }); + + registry.inject_broadcast(job_refs); +} diff --git a/vendor/rayon-core/src/broadcast/test.rs b/vendor/rayon-core/src/broadcast/test.rs new file mode 100755 index 000000000..a765cb034 --- /dev/null +++ b/vendor/rayon-core/src/broadcast/test.rs @@ -0,0 +1,216 @@ +#![cfg(test)] + +use crate::ThreadPoolBuilder; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use std::{thread, time}; + +#[test] +fn broadcast_global() { + let v = crate::broadcast(|ctx| ctx.index()); + assert!(v.into_iter().eq(0..crate::current_num_threads())); +} + +#[test] +fn spawn_broadcast_global() { + let (tx, rx) = crossbeam_channel::unbounded(); + crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap()); + + let mut v: Vec<_> = rx.into_iter().collect(); + v.sort_unstable(); + assert!(v.into_iter().eq(0..crate::current_num_threads())); +} + +#[test] +fn broadcast_pool() { + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + let v = pool.broadcast(|ctx| ctx.index()); + assert!(v.into_iter().eq(0..7)); +} + +#[test] +fn spawn_broadcast_pool() { + let (tx, rx) = crossbeam_channel::unbounded(); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + pool.spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap()); + + let mut v: Vec<_> = rx.into_iter().collect(); + v.sort_unstable(); + assert!(v.into_iter().eq(0..7)); +} + +#[test] +fn broadcast_self() { + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + let v = pool.install(|| crate::broadcast(|ctx| ctx.index())); + assert!(v.into_iter().eq(0..7)); +} + +#[test] +fn spawn_broadcast_self() { + let (tx, rx) = crossbeam_channel::unbounded(); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + pool.spawn(|| crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap())); + + let mut v: Vec<_> = rx.into_iter().collect(); + v.sort_unstable(); + assert!(v.into_iter().eq(0..7)); +} + +#[test] +fn broadcast_mutual() { + let count = AtomicUsize::new(0); + let pool1 = ThreadPoolBuilder::new().num_threads(3).build().unwrap(); + let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + pool1.install(|| { + pool2.broadcast(|_| { + pool1.broadcast(|_| { + count.fetch_add(1, Ordering::Relaxed); + }) + }) + }); + assert_eq!(count.into_inner(), 3 * 7); +} + +#[test] +fn spawn_broadcast_mutual() { + let (tx, rx) = crossbeam_channel::unbounded(); + let pool1 = Arc::new(ThreadPoolBuilder::new().num_threads(3).build().unwrap()); + let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + pool1.spawn({ + let pool1 = Arc::clone(&pool1); + move || { + pool2.spawn_broadcast(move |_| { + let tx = tx.clone(); + pool1.spawn_broadcast(move |_| tx.send(()).unwrap()) + }) + } + }); + assert_eq!(rx.into_iter().count(), 3 * 7); +} + +#[test] +fn broadcast_mutual_sleepy() { + let count = AtomicUsize::new(0); + let pool1 = ThreadPoolBuilder::new().num_threads(3).build().unwrap(); + let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + pool1.install(|| { + thread::sleep(time::Duration::from_secs(1)); + pool2.broadcast(|_| { + thread::sleep(time::Duration::from_secs(1)); + pool1.broadcast(|_| { + thread::sleep(time::Duration::from_millis(100)); + count.fetch_add(1, Ordering::Relaxed); + }) + }) + }); + assert_eq!(count.into_inner(), 3 * 7); +} + +#[test] +fn spawn_broadcast_mutual_sleepy() { + let (tx, rx) = crossbeam_channel::unbounded(); + let pool1 = Arc::new(ThreadPoolBuilder::new().num_threads(3).build().unwrap()); + let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + pool1.spawn({ + let pool1 = Arc::clone(&pool1); + move || { + thread::sleep(time::Duration::from_secs(1)); + pool2.spawn_broadcast(move |_| { + let tx = tx.clone(); + thread::sleep(time::Duration::from_secs(1)); + pool1.spawn_broadcast(move |_| { + thread::sleep(time::Duration::from_millis(100)); + tx.send(()).unwrap(); + }) + }) + } + }); + assert_eq!(rx.into_iter().count(), 3 * 7); +} + +#[test] +fn broadcast_panic_one() { + let count = AtomicUsize::new(0); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + let result = crate::unwind::halt_unwinding(|| { + pool.broadcast(|ctx| { + count.fetch_add(1, Ordering::Relaxed); + if ctx.index() == 3 { + panic!("Hello, world!"); + } + }) + }); + assert_eq!(count.into_inner(), 7); + assert!(result.is_err(), "broadcast panic should propagate!"); +} + +#[test] +fn spawn_broadcast_panic_one() { + let (tx, rx) = crossbeam_channel::unbounded(); + let (panic_tx, panic_rx) = crossbeam_channel::unbounded(); + let pool = ThreadPoolBuilder::new() + .num_threads(7) + .panic_handler(move |e| panic_tx.send(e).unwrap()) + .build() + .unwrap(); + pool.spawn_broadcast(move |ctx| { + tx.send(()).unwrap(); + if ctx.index() == 3 { + panic!("Hello, world!"); + } + }); + drop(pool); // including panic_tx + assert_eq!(rx.into_iter().count(), 7); + assert_eq!(panic_rx.into_iter().count(), 1); +} + +#[test] +fn broadcast_panic_many() { + let count = AtomicUsize::new(0); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + let result = crate::unwind::halt_unwinding(|| { + pool.broadcast(|ctx| { + count.fetch_add(1, Ordering::Relaxed); + if ctx.index() % 2 == 0 { + panic!("Hello, world!"); + } + }) + }); + assert_eq!(count.into_inner(), 7); + assert!(result.is_err(), "broadcast panic should propagate!"); +} + +#[test] +fn spawn_broadcast_panic_many() { + let (tx, rx) = crossbeam_channel::unbounded(); + let (panic_tx, panic_rx) = crossbeam_channel::unbounded(); + let pool = ThreadPoolBuilder::new() + .num_threads(7) + .panic_handler(move |e| panic_tx.send(e).unwrap()) + .build() + .unwrap(); + pool.spawn_broadcast(move |ctx| { + tx.send(()).unwrap(); + if ctx.index() % 2 == 0 { + panic!("Hello, world!"); + } + }); + drop(pool); // including panic_tx + assert_eq!(rx.into_iter().count(), 7); + assert_eq!(panic_rx.into_iter().count(), 4); +} + +#[test] +fn broadcast_sleep_race() { + let test_duration = time::Duration::from_secs(1); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + let start = time::Instant::now(); + while start.elapsed() < test_duration { + pool.broadcast(|ctx| { + // A slight spread of sleep duration increases the chance that one + // of the threads will race in the pool's idle sleep afterward. + thread::sleep(time::Duration::from_micros(ctx.index() as u64)); + }); + } +} diff --git a/vendor/rayon-core/src/compile_fail/rc_return.rs b/vendor/rayon-core/src/compile_fail/rc_return.rs index 164f8ce5e..93e3a6038 100644 --- a/vendor/rayon-core/src/compile_fail/rc_return.rs +++ b/vendor/rayon-core/src/compile_fail/rc_return.rs @@ -2,9 +2,7 @@ use std::rc::Rc; -fn main() { - rayon_core::join(|| Rc::new(22), || ()); //~ ERROR -} +rayon_core::join(|| Rc::new(22), || ()); //~ ERROR ``` */ mod left {} @@ -13,9 +11,7 @@ mod left {} use std::rc::Rc; -fn main() { - rayon_core::join(|| (), || Rc::new(23)); //~ ERROR -} +rayon_core::join(|| (), || Rc::new(23)); //~ ERROR ``` */ mod right {} diff --git a/vendor/rayon-core/src/compile_fail/rc_upvar.rs b/vendor/rayon-core/src/compile_fail/rc_upvar.rs index 62895bf22..d8aebcfcb 100644 --- a/vendor/rayon-core/src/compile_fail/rc_upvar.rs +++ b/vendor/rayon-core/src/compile_fail/rc_upvar.rs @@ -2,10 +2,8 @@ use std::rc::Rc; -fn main() { - let r = Rc::new(22); - rayon_core::join(|| r.clone(), || r.clone()); - //~^ ERROR -} +let r = Rc::new(22); +rayon_core::join(|| r.clone(), || r.clone()); +//~^ ERROR ``` */ diff --git a/vendor/rayon-core/src/job.rs b/vendor/rayon-core/src/job.rs index a71f1b0e9..b7a3dae18 100644 --- a/vendor/rayon-core/src/job.rs +++ b/vendor/rayon-core/src/job.rs @@ -4,6 +4,7 @@ use crossbeam_deque::{Injector, Steal}; use std::any::Any; use std::cell::UnsafeCell; use std::mem; +use std::sync::Arc; pub(super) enum JobResult<T> { None, @@ -20,7 +21,7 @@ pub(super) trait Job { /// Unsafe: this may be called from a different thread than the one /// which scheduled the job, so the implementer must ensure the /// appropriate traits are met, whether `Send`, `Sync`, or both. - unsafe fn execute(this: *const Self); + unsafe fn execute(this: *const ()); } /// Effectively a Job trait object. Each JobRef **must** be executed @@ -45,17 +46,15 @@ impl JobRef { where T: Job, { - let fn_ptr: unsafe fn(*const T) = <T as Job>::execute; - // erase types: JobRef { pointer: data as *const (), - execute_fn: mem::transmute(fn_ptr), + execute_fn: <T as Job>::execute, } } #[inline] - pub(super) unsafe fn execute(&self) { + pub(super) unsafe fn execute(self) { (self.execute_fn)(self.pointer) } } @@ -108,18 +107,11 @@ where F: FnOnce(bool) -> R + Send, R: Send, { - unsafe fn execute(this: *const Self) { - fn call<R>(func: impl FnOnce(bool) -> R) -> impl FnOnce() -> R { - move || func(true) - } - - let this = &*this; + unsafe fn execute(this: *const ()) { + let this = &*(this as *const Self); let abort = unwind::AbortIfPanic; let func = (*this.func.get()).take().unwrap(); - (*this.result.get()) = match unwind::halt_unwinding(call(func)) { - Ok(x) => JobResult::Ok(x), - Err(x) => JobResult::Panic(x), - }; + (*this.result.get()) = JobResult::call(func); this.latch.set(); mem::forget(abort); } @@ -135,25 +127,30 @@ pub(super) struct HeapJob<BODY> where BODY: FnOnce() + Send, { - job: UnsafeCell<Option<BODY>>, + job: BODY, } impl<BODY> HeapJob<BODY> where BODY: FnOnce() + Send, { - pub(super) fn new(func: BODY) -> Self { - HeapJob { - job: UnsafeCell::new(Some(func)), - } + pub(super) fn new(job: BODY) -> Box<Self> { + Box::new(HeapJob { job }) } /// Creates a `JobRef` from this job -- note that this hides all /// lifetimes, so it is up to you to ensure that this JobRef /// doesn't outlive any data that it closes over. - pub(super) unsafe fn as_job_ref(self: Box<Self>) -> JobRef { - let this: *const Self = mem::transmute(self); - JobRef::new(this) + pub(super) unsafe fn into_job_ref(self: Box<Self>) -> JobRef { + JobRef::new(Box::into_raw(self)) + } + + /// Creates a static `JobRef` from this job. + pub(super) fn into_static_job_ref(self: Box<Self>) -> JobRef + where + BODY: 'static, + { + unsafe { self.into_job_ref() } } } @@ -161,14 +158,63 @@ impl<BODY> Job for HeapJob<BODY> where BODY: FnOnce() + Send, { - unsafe fn execute(this: *const Self) { - let this: Box<Self> = mem::transmute(this); - let job = (*this.job.get()).take().unwrap(); - job(); + unsafe fn execute(this: *const ()) { + let this = Box::from_raw(this as *mut Self); + (this.job)(); + } +} + +/// Represents a job stored in an `Arc` -- like `HeapJob`, but may +/// be turned into multiple `JobRef`s and called multiple times. +pub(super) struct ArcJob<BODY> +where + BODY: Fn() + Send + Sync, +{ + job: BODY, +} + +impl<BODY> ArcJob<BODY> +where + BODY: Fn() + Send + Sync, +{ + pub(super) fn new(job: BODY) -> Arc<Self> { + Arc::new(ArcJob { job }) + } + + /// Creates a `JobRef` from this job -- note that this hides all + /// lifetimes, so it is up to you to ensure that this JobRef + /// doesn't outlive any data that it closes over. + pub(super) unsafe fn as_job_ref(this: &Arc<Self>) -> JobRef { + JobRef::new(Arc::into_raw(Arc::clone(this))) + } + + /// Creates a static `JobRef` from this job. + pub(super) fn as_static_job_ref(this: &Arc<Self>) -> JobRef + where + BODY: 'static, + { + unsafe { Self::as_job_ref(this) } + } +} + +impl<BODY> Job for ArcJob<BODY> +where + BODY: Fn() + Send + Sync, +{ + unsafe fn execute(this: *const ()) { + let this = Arc::from_raw(this as *mut Self); + (this.job)(); } } impl<T> JobResult<T> { + fn call(func: impl FnOnce(bool) -> T) -> Self { + match unwind::halt_unwinding(|| func(true)) { + Ok(x) => JobResult::Ok(x), + Err(x) => JobResult::Panic(x), + } + } + /// Convert the `JobResult` for a job that has finished (and hence /// its JobResult is populated) into its return value. /// @@ -204,10 +250,11 @@ impl JobFifo { } impl Job for JobFifo { - unsafe fn execute(this: *const Self) { + unsafe fn execute(this: *const ()) { // We "execute" a queue by executing its first job, FIFO. + let this = &*(this as *const Self); loop { - match (*this).inner.steal() { + match this.inner.steal() { Steal::Success(job_ref) => break job_ref.execute(), Steal::Empty => panic!("FIFO is empty"), Steal::Retry => {} diff --git a/vendor/rayon-core/src/latch.rs b/vendor/rayon-core/src/latch.rs index b84fbe371..090929374 100644 --- a/vendor/rayon-core/src/latch.rs +++ b/vendor/rayon-core/src/latch.rs @@ -196,14 +196,14 @@ impl<'r> Latch for SpinLatch<'r> { // the registry to be deallocated, all before we get a // chance to invoke `registry.notify_worker_latch_is_set`. cross_registry = Arc::clone(self.registry); - &*cross_registry + &cross_registry } else { // If this is not a "cross-registry" spin-latch, then the // thread which is performing `set` is itself ensuring // that the registry stays alive. However, that doesn't // include this *particular* `Arc` handle if the waiting // thread then exits, so we must completely dereference it. - &**self.registry + self.registry }; let target_worker_index = self.target_worker_index; @@ -286,9 +286,14 @@ pub(super) struct CountLatch { impl CountLatch { #[inline] pub(super) fn new() -> CountLatch { + Self::with_count(1) + } + + #[inline] + pub(super) fn with_count(n: usize) -> CountLatch { CountLatch { core_latch: CoreLatch::new(), - counter: AtomicUsize::new(1), + counter: AtomicUsize::new(n), } } @@ -337,10 +342,10 @@ pub(super) struct CountLockLatch { impl CountLockLatch { #[inline] - pub(super) fn new() -> CountLockLatch { + pub(super) fn with_count(n: usize) -> CountLockLatch { CountLockLatch { lock_latch: LockLatch::new(), - counter: AtomicUsize::new(1), + counter: AtomicUsize::new(n), } } diff --git a/vendor/rayon-core/src/lib.rs b/vendor/rayon-core/src/lib.rs index 246b80070..b31a2d7e0 100644 --- a/vendor/rayon-core/src/lib.rs +++ b/vendor/rayon-core/src/lib.rs @@ -44,7 +44,6 @@ //! conflicting requirements will need to be resolved before the build will //! succeed. -#![doc(html_root_url = "https://docs.rs/rayon-core/1.9")] #![deny(missing_debug_implementations)] #![deny(missing_docs)] #![deny(unreachable_pub)] @@ -63,6 +62,7 @@ mod log; #[macro_use] mod private; +mod broadcast; mod job; mod join; mod latch; @@ -76,6 +76,7 @@ mod unwind; mod compile_fail; mod test; +pub use self::broadcast::{broadcast, spawn_broadcast, BroadcastContext}; pub use self::join::{join, join_context}; pub use self::registry::ThreadBuilder; pub use self::scope::{in_place_scope, scope, Scope}; @@ -185,6 +186,7 @@ pub struct ThreadPoolBuilder<S = DefaultSpawn> { /// /// [`ThreadPoolBuilder`]: struct.ThreadPoolBuilder.html #[deprecated(note = "Use `ThreadPoolBuilder`")] +#[derive(Default)] pub struct Configuration { builder: ThreadPoolBuilder, } @@ -269,7 +271,7 @@ impl ThreadPoolBuilder { /// The threads in this pool will start by calling `wrapper`, which should /// do initialization and continue by calling `ThreadBuilder::run()`. /// - /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.7/crossbeam/fn.scope.html + /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.8/crossbeam/fn.scope.html /// /// # Examples /// @@ -339,7 +341,7 @@ impl<S> ThreadPoolBuilder<S> { /// if the pool is leaked. Furthermore, the global thread pool doesn't terminate /// until the entire process exits! /// - /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.7/crossbeam/fn.scope.html + /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.8/crossbeam/fn.scope.html /// /// # Examples /// @@ -384,6 +386,39 @@ impl<S> ThreadPoolBuilder<S> { /// Ok(()) /// } /// ``` + /// + /// This can also be used for a pool of scoped threads like [`crossbeam::scope`], + /// or [`std::thread::scope`] introduced in Rust 1.63, which is encapsulated in + /// [`build_scoped`](#method.build_scoped). + /// + /// [`std::thread::scope`]: https://doc.rust-lang.org/std/thread/fn.scope.html + /// + /// ``` + /// # use rayon_core as rayon; + /// fn main() -> Result<(), rayon::ThreadPoolBuildError> { + /// std::thread::scope(|scope| { + /// let pool = rayon::ThreadPoolBuilder::new() + /// .spawn_handler(|thread| { + /// let mut builder = std::thread::Builder::new(); + /// if let Some(name) = thread.name() { + /// builder = builder.name(name.to_string()); + /// } + /// if let Some(size) = thread.stack_size() { + /// builder = builder.stack_size(size); + /// } + /// builder.spawn_scoped(scope, || { + /// // Add any scoped initialization here, then run! + /// thread.run() + /// })?; + /// Ok(()) + /// }) + /// .build()?; + /// + /// pool.install(|| println!("Hello from my custom scoped thread!")); + /// Ok(()) + /// }) + /// } + /// ``` pub fn spawn_handler<F>(self, spawn: F) -> ThreadPoolBuilder<CustomSpawn<F>> where F: FnMut(ThreadBuilder) -> io::Result<()>, @@ -526,7 +561,7 @@ impl<S> ThreadPoolBuilder<S> { /// to true, however, workers will prefer to execute in a /// *breadth-first* fashion -- that is, they will search for jobs at /// the *bottom* of their local deque. (At present, workers *always* - /// steal from the bottom of other worker's deques, regardless of + /// steal from the bottom of other workers' deques, regardless of /// the setting of this flag.) /// /// If you think of the tasks as a tree, where a parent task @@ -749,15 +784,6 @@ impl<S> fmt::Debug for ThreadPoolBuilder<S> { } #[allow(deprecated)] -impl Default for Configuration { - fn default() -> Self { - Configuration { - builder: Default::default(), - } - } -} - -#[allow(deprecated)] impl fmt::Debug for Configuration { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.builder.fmt(f) diff --git a/vendor/rayon-core/src/log.rs b/vendor/rayon-core/src/log.rs index e1ff827df..7b6daf0ab 100644 --- a/vendor/rayon-core/src/log.rs +++ b/vendor/rayon-core/src/log.rs @@ -93,6 +93,9 @@ pub(super) enum Event { /// A job was removed from the global queue. JobUninjected { worker: usize }, + /// A job was broadcasted to N threads. + JobBroadcast { count: usize }, + /// When announcing a job, this was the value of the counters we observed. /// /// No effect on thread state, just a debugging event. @@ -124,15 +127,15 @@ impl Logger { let (sender, receiver) = crossbeam_channel::unbounded(); - if env_log.starts_with("tail:") { - let filename = env_log["tail:".len()..].to_string(); + if let Some(filename) = env_log.strip_prefix("tail:") { + let filename = filename.to_string(); ::std::thread::spawn(move || { Self::tail_logger_thread(num_workers, filename, 10_000, receiver) }); } else if env_log == "all" { ::std::thread::spawn(move || Self::all_logger_thread(num_workers, receiver)); - } else if env_log.starts_with("profile:") { - let filename = env_log["profile:".len()..].to_string(); + } else if let Some(filename) = env_log.strip_prefix("profile:") { + let filename = filename.to_string(); ::std::thread::spawn(move || { Self::profile_logger_thread(num_workers, filename, 10_000, receiver) }); @@ -140,9 +143,9 @@ impl Logger { panic!("RAYON_LOG should be 'tail:<file>' or 'profile:<file>'"); } - return Logger { + Logger { sender: Some(sender), - }; + } } fn disabled() -> Logger { @@ -175,19 +178,12 @@ impl Logger { let timeout = std::time::Duration::from_secs(30); loop { - loop { - match receiver.recv_timeout(timeout) { - Ok(event) => { - if let Event::Flush = event { - break; - } else { - events.push(event); - } - } - - Err(_) => break, + while let Ok(event) = receiver.recv_timeout(timeout) { + if let Event::Flush = event { + break; } + events.push(event); if events.len() == capacity { break; } @@ -219,31 +215,25 @@ impl Logger { let mut skipped = false; loop { - loop { - match receiver.recv_timeout(timeout) { - Ok(event) => { - if let Event::Flush = event { - // We ignore Flush events in tail mode -- - // we're really just looking for - // deadlocks. - continue; - } else { - if events.len() == capacity { - let event = events.pop_front().unwrap(); - state.simulate(&event); - skipped = true; - } - - events.push_back(event); - } + while let Ok(event) = receiver.recv_timeout(timeout) { + if let Event::Flush = event { + // We ignore Flush events in tail mode -- + // we're really just looking for + // deadlocks. + continue; + } else { + if events.len() == capacity { + let event = events.pop_front().unwrap(); + state.simulate(&event); + skipped = true; } - Err(_) => break, + events.push_back(event); } } if skipped { - write!(writer, "...\n").unwrap(); + writeln!(writer, "...").unwrap(); skipped = false; } @@ -417,7 +407,7 @@ impl SimulatorState { } } - write!(w, "\n")?; + writeln!(w)?; Ok(()) } } diff --git a/vendor/rayon-core/src/registry.rs b/vendor/rayon-core/src/registry.rs index 7405fe8e7..279e298d2 100644 --- a/vendor/rayon-core/src/registry.rs +++ b/vendor/rayon-core/src/registry.rs @@ -8,7 +8,6 @@ use crate::{ ErrorKind, ExitHandler, PanicHandler, StartHandler, ThreadPoolBuildError, ThreadPoolBuilder, }; use crossbeam_deque::{Injector, Steal, Stealer, Worker}; -use std::any::Any; use std::cell::Cell; use std::collections::hash_map::DefaultHasher; use std::fmt; @@ -16,10 +15,8 @@ use std::hash::Hasher; use std::io; use std::mem; use std::ptr; -#[allow(deprecated)] -use std::sync::atomic::ATOMIC_USIZE_INIT; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{Arc, Once}; +use std::sync::{Arc, Mutex, Once}; use std::thread; use std::usize; @@ -29,6 +26,7 @@ pub struct ThreadBuilder { name: Option<String>, stack_size: Option<usize>, worker: Worker<JobRef>, + stealer: Stealer<JobRef>, registry: Arc<Registry>, index: usize, } @@ -41,7 +39,7 @@ impl ThreadBuilder { /// Gets the string that was specified by `ThreadPoolBuilder::name()`. pub fn name(&self) -> Option<&str> { - self.name.as_ref().map(String::as_str) + self.name.as_deref() } /// Gets the value that was specified by `ThreadPoolBuilder::stack_size()`. @@ -52,7 +50,7 @@ impl ThreadBuilder { /// Executes the main loop for this thread. This will not return until the /// thread pool is dropped. pub fn run(self) { - unsafe { main_loop(self.worker, self.registry, self.index) } + unsafe { main_loop(self.worker, self.stealer, self.registry, self.index) } } } @@ -135,6 +133,7 @@ pub(super) struct Registry { thread_infos: Vec<ThreadInfo>, sleep: Sleep, injected_jobs: Injector<JobRef>, + broadcasts: Mutex<Vec<Worker<JobRef>>>, panic_handler: Option<Box<PanicHandler>>, start_handler: Option<Box<StartHandler>>, exit_handler: Option<Box<ExitHandler>>, @@ -232,12 +231,21 @@ impl Registry { }) .unzip(); + let (broadcasts, broadcast_stealers): (Vec<_>, Vec<_>) = (0..n_threads) + .map(|_| { + let worker = Worker::new_fifo(); + let stealer = worker.stealer(); + (worker, stealer) + }) + .unzip(); + let logger = Logger::new(n_threads); let registry = Arc::new(Registry { logger: logger.clone(), thread_infos: stealers.into_iter().map(ThreadInfo::new).collect(), sleep: Sleep::new(logger, n_threads), injected_jobs: Injector::new(), + broadcasts: Mutex::new(broadcasts), terminate_count: AtomicUsize::new(1), panic_handler: builder.take_panic_handler(), start_handler: builder.take_start_handler(), @@ -247,12 +255,13 @@ impl Registry { // If we return early or panic, make sure to terminate existing threads. let t1000 = Terminator(®istry); - for (index, worker) in workers.into_iter().enumerate() { + for (index, (worker, stealer)) in workers.into_iter().zip(broadcast_stealers).enumerate() { let thread = ThreadBuilder { name: builder.get_thread_name(index), stack_size: builder.get_stack_size(), registry: Arc::clone(®istry), worker, + stealer, index, }; if let Err(e) = builder.get_spawn_handler().spawn(thread) { @@ -322,19 +331,14 @@ impl Registry { self.thread_infos.len() } - pub(super) fn handle_panic(&self, err: Box<dyn Any + Send>) { - match self.panic_handler { - Some(ref handler) => { - // If the customizable panic handler itself panics, - // then we abort. - let abort_guard = unwind::AbortIfPanic; + pub(super) fn catch_unwind(&self, f: impl FnOnce()) { + if let Err(err) = unwind::halt_unwinding(f) { + // If there is no handler, or if that handler itself panics, then we abort. + let abort_guard = unwind::AbortIfPanic; + if let Some(ref handler) = self.panic_handler { handler(err); mem::forget(abort_guard); } - None => { - // Default panic handler aborts. - let _ = unwind::AbortIfPanic; // let this drop. - } } } @@ -378,7 +382,7 @@ impl Registry { } /// Push a job into the "external jobs" queue; it will be taken by - /// whatever worker has nothing to do. Use this is you know that + /// whatever worker has nothing to do. Use this if you know that /// you are not on a worker of this registry. pub(super) fn inject(&self, injected_jobs: &[JobRef]) { self.log(|| JobsInjected { @@ -425,6 +429,40 @@ impl Registry { } } + /// Push a job into each thread's own "external jobs" queue; it will be + /// executed only on that thread, when it has nothing else to do locally, + /// before it tries to steal other work. + /// + /// **Panics** if not given exactly as many jobs as there are threads. + pub(super) fn inject_broadcast(&self, injected_jobs: impl ExactSizeIterator<Item = JobRef>) { + assert_eq!(self.num_threads(), injected_jobs.len()); + self.log(|| JobBroadcast { + count: self.num_threads(), + }); + { + let broadcasts = self.broadcasts.lock().unwrap(); + + // It should not be possible for `state.terminate` to be true + // here. It is only set to true when the user creates (and + // drops) a `ThreadPool`; and, in that case, they cannot be + // calling `inject_broadcast()` later, since they dropped their + // `ThreadPool`. + debug_assert_ne!( + self.terminate_count.load(Ordering::Acquire), + 0, + "inject_broadcast() sees state.terminate as true" + ); + + assert_eq!(broadcasts.len(), injected_jobs.len()); + for (worker, job_ref) in broadcasts.iter().zip(injected_jobs) { + worker.push(job_ref); + } + } + for i in 0..self.num_threads() { + self.sleep.notify_worker_latch_is_set(i); + } + } + /// If already in a worker-thread of this registry, just execute `op`. /// Otherwise, inject `op` in this thread-pool. Either way, block until `op` /// completes and return its return value. If `op` panics, that panic will @@ -594,6 +632,9 @@ pub(super) struct WorkerThread { /// the "worker" half of our local deque worker: Worker<JobRef>, + /// the "stealer" half of the worker's broadcast deque + stealer: Stealer<JobRef>, + /// local queue used for `spawn_fifo` indirection fifo: JobFifo, @@ -689,9 +730,20 @@ impl WorkerThread { if popped_job.is_some() { self.log(|| JobPopped { worker: self.index }); + return popped_job; } - popped_job + loop { + match self.stealer.steal() { + Steal::Success(job) => return Some(job), + Steal::Empty => return None, + Steal::Retry => {} + } + } + } + + fn has_injected_job(&self) -> bool { + !self.stealer.is_empty() || self.registry.has_injected_job() } /// Wait until the latch is set. Try to keep busy by popping and @@ -731,7 +783,7 @@ impl WorkerThread { } else { self.registry .sleep - .no_work_found(&mut idle_state, latch, || self.registry.has_injected_job()) + .no_work_found(&mut idle_state, latch, || self.has_injected_job()) } } @@ -799,9 +851,15 @@ impl WorkerThread { /// //////////////////////////////////////////////////////////////////////// -unsafe fn main_loop(worker: Worker<JobRef>, registry: Arc<Registry>, index: usize) { +unsafe fn main_loop( + worker: Worker<JobRef>, + stealer: Stealer<JobRef>, + registry: Arc<Registry>, + index: usize, +) { let worker_thread = &WorkerThread { worker, + stealer, fifo: JobFifo::new(), index, rng: XorShift64Star::new(), @@ -820,12 +878,7 @@ unsafe fn main_loop(worker: Worker<JobRef>, registry: Arc<Registry>, index: usiz // Inform a user callback that we started a thread. if let Some(ref handler) = registry.start_handler { - match unwind::halt_unwinding(|| handler(index)) { - Ok(()) => {} - Err(err) => { - registry.handle_panic(err); - } - } + registry.catch_unwind(|| handler(index)); } let my_terminate_latch = ®istry.thread_infos[index].terminate; @@ -848,12 +901,7 @@ unsafe fn main_loop(worker: Worker<JobRef>, registry: Arc<Registry>, index: usiz // Inform a user callback that we exited a thread. if let Some(ref handler) = registry.exit_handler { - match unwind::halt_unwinding(|| handler(index)) { - Ok(()) => {} - Err(err) => { - registry.handle_panic(err); - } - } + registry.catch_unwind(|| handler(index)); // We're already exiting the thread, there's nothing else to do. } } @@ -895,8 +943,7 @@ impl XorShift64Star { let mut seed = 0; while seed == 0 { let mut hasher = DefaultHasher::new(); - #[allow(deprecated)] - static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + static COUNTER: AtomicUsize = AtomicUsize::new(0); hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed)); seed = hasher.finish(); } diff --git a/vendor/rayon-core/src/scope/mod.rs b/vendor/rayon-core/src/scope/mod.rs index f8d90ce20..25cda832e 100644 --- a/vendor/rayon-core/src/scope/mod.rs +++ b/vendor/rayon-core/src/scope/mod.rs @@ -5,7 +5,8 @@ //! [`in_place_scope()`]: fn.in_place_scope.html //! [`join()`]: ../join/join.fn.html -use crate::job::{HeapJob, JobFifo}; +use crate::broadcast::BroadcastContext; +use crate::job::{ArcJob, HeapJob, JobFifo, JobRef}; use crate::latch::{CountLatch, CountLockLatch, Latch}; use crate::registry::{global_registry, in_worker, Registry, WorkerThread}; use crate::unwind; @@ -38,7 +39,7 @@ pub struct ScopeFifo<'scope> { fifos: Vec<JobFifo>, } -enum ScopeLatch { +pub(super) enum ScopeLatch { /// A latch for scopes created on a rayon thread which will participate in work- /// stealing while it waits for completion. This thread is not necessarily part /// of the same registry as the scope itself! @@ -127,7 +128,7 @@ struct ScopeBase<'scope> { /// Task execution potentially starts as soon as `spawn()` is called. /// The task will end sometime before `scope()` returns. Note that the /// *closure* given to scope may return much earlier. In general -/// the lifetime of a scope created like `scope(body) goes something like this: +/// the lifetime of a scope created like `scope(body)` goes something like this: /// /// - Scope begins when `scope(body)` is called /// - Scope body `body()` is invoked @@ -241,7 +242,7 @@ struct ScopeBase<'scope> { /// }); /// /// // That closure is fine, but now we can't use `ok` anywhere else, -/// // since it is owend by the previous task: +/// // since it is owned by the previous task: /// // s.spawn(|_| println!("ok: {:?}", ok)); /// }); /// ``` @@ -538,18 +539,37 @@ impl<'scope> Scope<'scope> { where BODY: FnOnce(&Scope<'scope>) + Send + 'scope, { - self.base.increment(); - unsafe { - let job_ref = Box::new(HeapJob::new(move || { - self.base.execute_job(move || body(self)) - })) - .as_job_ref(); - - // Since `Scope` implements `Sync`, we can't be sure that we're still in a - // thread of this pool, so we can't just push to the local worker thread. - // Also, this might be an in-place scope. - self.base.registry.inject_or_push(job_ref); - } + let scope_ptr = ScopePtr(self); + let job = HeapJob::new(move || { + // SAFETY: this job will execute before the scope ends. + let scope = unsafe { scope_ptr.as_ref() }; + scope.base.execute_job(move || body(scope)) + }); + let job_ref = self.base.heap_job_ref(job); + + // Since `Scope` implements `Sync`, we can't be sure that we're still in a + // thread of this pool, so we can't just push to the local worker thread. + // Also, this might be an in-place scope. + self.base.registry.inject_or_push(job_ref); + } + + /// Spawns a job into every thread of the fork-join scope `self`. This job will + /// execute on each thread sometime before the fork-join scope completes. The + /// job is specified as a closure, and this closure receives its own reference + /// to the scope `self` as argument, as well as a `BroadcastContext`. + pub fn spawn_broadcast<BODY>(&self, body: BODY) + where + BODY: Fn(&Scope<'scope>, BroadcastContext<'_>) + Send + Sync + 'scope, + { + let scope_ptr = ScopePtr(self); + let job = ArcJob::new(move || { + // SAFETY: this job will execute before the scope ends. + let scope = unsafe { scope_ptr.as_ref() }; + let body = &body; + let func = move || BroadcastContext::with(move |ctx| body(scope, ctx)); + scope.base.execute_job(func); + }); + self.base.inject_broadcast(job) } } @@ -579,24 +599,44 @@ impl<'scope> ScopeFifo<'scope> { where BODY: FnOnce(&ScopeFifo<'scope>) + Send + 'scope, { - self.base.increment(); - unsafe { - let job_ref = Box::new(HeapJob::new(move || { - self.base.execute_job(move || body(self)) - })) - .as_job_ref(); - - // If we're in the pool, use our scope's private fifo for this thread to execute - // in a locally-FIFO order. Otherwise, just use the pool's global injector. - match self.base.registry.current_thread() { - Some(worker) => { - let fifo = &self.fifos[worker.index()]; - worker.push(fifo.push(job_ref)); - } - None => self.base.registry.inject(&[job_ref]), + let scope_ptr = ScopePtr(self); + let job = HeapJob::new(move || { + // SAFETY: this job will execute before the scope ends. + let scope = unsafe { scope_ptr.as_ref() }; + scope.base.execute_job(move || body(scope)) + }); + let job_ref = self.base.heap_job_ref(job); + + // If we're in the pool, use our scope's private fifo for this thread to execute + // in a locally-FIFO order. Otherwise, just use the pool's global injector. + match self.base.registry.current_thread() { + Some(worker) => { + let fifo = &self.fifos[worker.index()]; + // SAFETY: this job will execute before the scope ends. + unsafe { worker.push(fifo.push(job_ref)) }; } + None => self.base.registry.inject(&[job_ref]), } } + + /// Spawns a job into every thread of the fork-join scope `self`. This job will + /// execute on each thread sometime before the fork-join scope completes. The + /// job is specified as a closure, and this closure receives its own reference + /// to the scope `self` as argument, as well as a `BroadcastContext`. + pub fn spawn_broadcast<BODY>(&self, body: BODY) + where + BODY: Fn(&ScopeFifo<'scope>, BroadcastContext<'_>) + Send + Sync + 'scope, + { + let scope_ptr = ScopePtr(self); + let job = ArcJob::new(move || { + // SAFETY: this job will execute before the scope ends. + let scope = unsafe { scope_ptr.as_ref() }; + let body = &body; + let func = move || BroadcastContext::with(move |ctx| body(scope, ctx)); + scope.base.execute_job(func); + }); + self.base.inject_broadcast(job) + } } impl<'scope> ScopeBase<'scope> { @@ -619,6 +659,29 @@ impl<'scope> ScopeBase<'scope> { self.job_completed_latch.increment(); } + fn heap_job_ref<FUNC>(&self, job: Box<HeapJob<FUNC>>) -> JobRef + where + FUNC: FnOnce() + Send + 'scope, + { + unsafe { + self.increment(); + job.into_job_ref() + } + } + + fn inject_broadcast<FUNC>(&self, job: Arc<ArcJob<FUNC>>) + where + FUNC: Fn() + Send + Sync + 'scope, + { + let n_threads = self.registry.num_threads(); + let job_refs = (0..n_threads).map(|_| unsafe { + self.increment(); + ArcJob::as_job_ref(&job) + }); + + self.registry.inject_broadcast(job_refs); + } + /// Executes `func` as a job, either aborting or executing as /// appropriate. fn complete<FUNC, R>(&self, owner: Option<&WorkerThread>, func: FUNC) -> R @@ -687,14 +750,18 @@ impl<'scope> ScopeBase<'scope> { impl ScopeLatch { fn new(owner: Option<&WorkerThread>) -> Self { + Self::with_count(1, owner) + } + + pub(super) fn with_count(count: usize, owner: Option<&WorkerThread>) -> Self { match owner { Some(owner) => ScopeLatch::Stealing { - latch: CountLatch::new(), + latch: CountLatch::with_count(count), registry: Arc::clone(owner.registry()), worker_index: owner.index(), }, None => ScopeLatch::Blocking { - latch: CountLockLatch::new(), + latch: CountLockLatch::with_count(count), }, } } @@ -706,30 +773,32 @@ impl ScopeLatch { } } - fn set(&self) { + pub(super) fn wait(&self, owner: Option<&WorkerThread>) { match self { ScopeLatch::Stealing { latch, registry, worker_index, - } => latch.set_and_tickle_one(registry, *worker_index), - ScopeLatch::Blocking { latch } => latch.set(), + } => unsafe { + let owner = owner.expect("owner thread"); + debug_assert_eq!(registry.id(), owner.registry().id()); + debug_assert_eq!(*worker_index, owner.index()); + owner.wait_until(latch); + }, + ScopeLatch::Blocking { latch } => latch.wait(), } } +} - fn wait(&self, owner: Option<&WorkerThread>) { +impl Latch for ScopeLatch { + fn set(&self) { match self { ScopeLatch::Stealing { latch, registry, worker_index, - } => unsafe { - let owner = owner.expect("owner thread"); - debug_assert_eq!(registry.id(), owner.registry().id()); - debug_assert_eq!(*worker_index, owner.index()); - owner.wait_until(latch); - }, - ScopeLatch::Blocking { latch } => latch.wait(), + } => latch.set_and_tickle_one(registry, *worker_index), + ScopeLatch::Blocking { latch } => latch.set(), } } } @@ -769,3 +838,22 @@ impl fmt::Debug for ScopeLatch { } } } + +/// Used to capture a scope `&Self` pointer in jobs, without faking a lifetime. +/// +/// Unsafe code is still required to dereference the pointer, but that's fine in +/// scope jobs that are guaranteed to execute before the scope ends. +struct ScopePtr<T>(*const T); + +// SAFETY: !Send for raw pointers is not for safety, just as a lint +unsafe impl<T: Sync> Send for ScopePtr<T> {} + +// SAFETY: !Sync for raw pointers is not for safety, just as a lint +unsafe impl<T: Sync> Sync for ScopePtr<T> {} + +impl<T> ScopePtr<T> { + // Helper to avoid disjoint captures of `scope_ptr.0` + unsafe fn as_ref(&self) -> &T { + &*self.0 + } +} diff --git a/vendor/rayon-core/src/scope/test.rs b/vendor/rayon-core/src/scope/test.rs index 88f9e9548..00dd18c92 100644 --- a/vendor/rayon-core/src/scope/test.rs +++ b/vendor/rayon-core/src/scope/test.rs @@ -6,7 +6,7 @@ use rand_xorshift::XorShiftRng; use std::cmp; use std::iter::once; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Mutex; +use std::sync::{Barrier, Mutex}; use std::vec; #[test] @@ -42,7 +42,7 @@ fn scope_divide_and_conquer() { scope(|s| s.spawn(move |s| divide_and_conquer(s, counter_p, 1024))); let counter_s = &AtomicUsize::new(0); - divide_and_conquer_seq(&counter_s, 1024); + divide_and_conquer_seq(counter_s, 1024); let p = counter_p.load(Ordering::SeqCst); let s = counter_s.load(Ordering::SeqCst); @@ -75,7 +75,7 @@ struct Tree<T: Send> { } impl<T: Send> Tree<T> { - fn iter<'s>(&'s self) -> vec::IntoIter<&'s T> { + fn iter(&self) -> vec::IntoIter<&T> { once(&self.value) .chain(self.children.iter().flat_map(Tree::iter)) .collect::<Vec<_>>() // seems like it shouldn't be needed... but prevents overflow @@ -513,3 +513,89 @@ fn mixed_lifetime_scope_fifo() { increment(&[&counter; 100]); assert_eq!(counter.into_inner(), 100); } + +#[test] +fn scope_spawn_broadcast() { + let sum = AtomicUsize::new(0); + let n = scope(|s| { + s.spawn_broadcast(|_, ctx| { + sum.fetch_add(ctx.index(), Ordering::Relaxed); + }); + crate::current_num_threads() + }); + assert_eq!(sum.into_inner(), n * (n - 1) / 2); +} + +#[test] +fn scope_fifo_spawn_broadcast() { + let sum = AtomicUsize::new(0); + let n = scope_fifo(|s| { + s.spawn_broadcast(|_, ctx| { + sum.fetch_add(ctx.index(), Ordering::Relaxed); + }); + crate::current_num_threads() + }); + assert_eq!(sum.into_inner(), n * (n - 1) / 2); +} + +#[test] +fn scope_spawn_broadcast_nested() { + let sum = AtomicUsize::new(0); + let n = scope(|s| { + s.spawn_broadcast(|s, _| { + s.spawn_broadcast(|_, ctx| { + sum.fetch_add(ctx.index(), Ordering::Relaxed); + }); + }); + crate::current_num_threads() + }); + assert_eq!(sum.into_inner(), n * n * (n - 1) / 2); +} + +#[test] +fn scope_spawn_broadcast_barrier() { + let barrier = Barrier::new(8); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + pool.in_place_scope(|s| { + s.spawn_broadcast(|_, _| { + barrier.wait(); + }); + barrier.wait(); + }); +} + +#[test] +fn scope_spawn_broadcast_panic_one() { + let count = AtomicUsize::new(0); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + let result = crate::unwind::halt_unwinding(|| { + pool.scope(|s| { + s.spawn_broadcast(|_, ctx| { + count.fetch_add(1, Ordering::Relaxed); + if ctx.index() == 3 { + panic!("Hello, world!"); + } + }); + }); + }); + assert_eq!(count.into_inner(), 7); + assert!(result.is_err(), "broadcast panic should propagate!"); +} + +#[test] +fn scope_spawn_broadcast_panic_many() { + let count = AtomicUsize::new(0); + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); + let result = crate::unwind::halt_unwinding(|| { + pool.scope(|s| { + s.spawn_broadcast(|_, ctx| { + count.fetch_add(1, Ordering::Relaxed); + if ctx.index() % 2 == 0 { + panic!("Hello, world!"); + } + }); + }); + }); + assert_eq!(count.into_inner(), 7); + assert!(result.is_err(), "broadcast panic should propagate!"); +} diff --git a/vendor/rayon-core/src/sleep/README.md b/vendor/rayon-core/src/sleep/README.md index c62c3975d..55426c88c 100644 --- a/vendor/rayon-core/src/sleep/README.md +++ b/vendor/rayon-core/src/sleep/README.md @@ -75,7 +75,7 @@ These counters are adjusted as follows: * When a thread awakens a sleeping thread: decrement the sleeping thread counter. * Subtle point: the thread that *awakens* the sleeping thread decrements the counter, not the thread that is *sleeping*. This is because there is a delay - between siganling a thread to wake and the thread actually waking: + between signaling a thread to wake and the thread actually waking: decrementing the counter when awakening the thread means that other threads that may be posting work will see the up-to-date value that much faster. * When a thread finds work, exiting the idle state: decrement the inactive @@ -137,7 +137,7 @@ The full protocol for a thread to fall asleep is as follows: above, remembering the `final_value` of the JEC. It does one more search for work. * If no work is found, the thread atomically: * Checks the JEC to see that it has not changed from `final_value`. - * If it has, then the thread goes back to searchin for work. We reset to + * If it has, then the thread goes back to searching for work. We reset to just before we got sleepy, so that we will do one more search before attending to sleep again (rather than searching for many rounds). * Increments the number of sleeping threads by 1. diff --git a/vendor/rayon-core/src/sleep/counters.rs b/vendor/rayon-core/src/sleep/counters.rs index 29d3b18e2..f2a3de3e1 100644 --- a/vendor/rayon-core/src/sleep/counters.rs +++ b/vendor/rayon-core/src/sleep/counters.rs @@ -61,10 +61,12 @@ const THREADS_BITS: usize = 8; /// Bits to shift to select the sleeping threads /// (used with `select_bits`). +#[allow(clippy::erasing_op)] const SLEEPING_SHIFT: usize = 0 * THREADS_BITS; /// Bits to shift to select the inactive threads /// (used with `select_bits`). +#[allow(clippy::identity_op)] const INACTIVE_SHIFT: usize = 1 * THREADS_BITS; /// Bits to shift to select the JEC diff --git a/vendor/rayon-core/src/sleep/mod.rs b/vendor/rayon-core/src/sleep/mod.rs index 2c4ac7c28..af7225a35 100644 --- a/vendor/rayon-core/src/sleep/mod.rs +++ b/vendor/rayon-core/src/sleep/mod.rs @@ -159,7 +159,7 @@ impl Sleep { debug_assert!(!*is_blocked); // Our latch was signalled. We should wake back up fully as we - // wil have some stuff to do. + // will have some stuff to do. if !latch.fall_asleep() { self.logger.log(|| ThreadSleepInterruptedByLatch { worker: worker_index, diff --git a/vendor/rayon-core/src/spawn/mod.rs b/vendor/rayon-core/src/spawn/mod.rs index dfa47818e..ae1f211ef 100644 --- a/vendor/rayon-core/src/spawn/mod.rs +++ b/vendor/rayon-core/src/spawn/mod.rs @@ -73,7 +73,7 @@ where F: FnOnce() + Send + 'static, { // We assert that this does not hold any references (we know - // this because of the `'static` bound in the inferface); + // this because of the `'static` bound in the interface); // moreover, we assert that the code below is not supposed to // be able to panic, and hence the data won't leak but will be // enqueued into some deque for later execution. @@ -91,19 +91,14 @@ where // executed. This ref is decremented at the (*) below. registry.increment_terminate_count(); - Box::new(HeapJob::new({ + HeapJob::new({ let registry = Arc::clone(registry); move || { - match unwind::halt_unwinding(func) { - Ok(()) => {} - Err(err) => { - registry.handle_panic(err); - } - } + registry.catch_unwind(func); registry.terminate(); // (*) permit registry to terminate now } - })) - .as_job_ref() + }) + .into_static_job_ref() } /// Fires off a task into the Rayon threadpool in the "static" or @@ -148,7 +143,7 @@ where F: FnOnce() + Send + 'static, { // We assert that this does not hold any references (we know - // this because of the `'static` bound in the inferface); + // this because of the `'static` bound in the interface); // moreover, we assert that the code below is not supposed to // be able to panic, and hence the data won't leak but will be // enqueued into some deque for later execution. diff --git a/vendor/rayon-core/src/test.rs b/vendor/rayon-core/src/test.rs index 600e58b11..46d63a7df 100644 --- a/vendor/rayon-core/src/test.rs +++ b/vendor/rayon-core/src/test.rs @@ -1,7 +1,5 @@ #![cfg(test)] -#[allow(deprecated)] -use crate::Configuration; use crate::{ThreadPoolBuildError, ThreadPoolBuilder}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Barrier}; @@ -121,7 +119,6 @@ fn handler_panics_handled_correctly() { } #[test] -#[allow(deprecated)] fn check_config_build() { let pool = ThreadPoolBuilder::new().num_threads(22).build().unwrap(); assert_eq!(pool.current_num_threads(), 22); @@ -144,7 +141,7 @@ fn configuration() { let thread_name = move |i| format!("thread_name_{}", i); // Ensure we can call all public methods on Configuration - Configuration::new() + crate::Configuration::new() .thread_name(thread_name) .num_threads(5) .panic_handler(panic_handler) diff --git a/vendor/rayon-core/src/thread_pool/mod.rs b/vendor/rayon-core/src/thread_pool/mod.rs index 5edaedc37..0fc06dd6b 100644 --- a/vendor/rayon-core/src/thread_pool/mod.rs +++ b/vendor/rayon-core/src/thread_pool/mod.rs @@ -3,12 +3,11 @@ //! //! [`ThreadPool`]: struct.ThreadPool.html +use crate::broadcast::{self, BroadcastContext}; use crate::join; use crate::registry::{Registry, ThreadSpawn, WorkerThread}; use crate::scope::{do_in_place_scope, do_in_place_scope_fifo}; use crate::spawn; -#[allow(deprecated)] -use crate::Configuration; use crate::{scope, Scope}; use crate::{scope_fifo, ScopeFifo}; use crate::{ThreadPoolBuildError, ThreadPoolBuilder}; @@ -57,7 +56,7 @@ impl ThreadPool { #[deprecated(note = "Use `ThreadPoolBuilder::build`")] #[allow(deprecated)] /// Deprecated in favor of `ThreadPoolBuilder::build`. - pub fn new(configuration: Configuration) -> Result<ThreadPool, Box<dyn Error>> { + pub fn new(configuration: crate::Configuration) -> Result<ThreadPool, Box<dyn Error>> { Self::build(configuration.into_builder()).map_err(Box::from) } @@ -111,6 +110,57 @@ impl ThreadPool { self.registry.in_worker(|_, _| op()) } + /// Executes `op` within every thread in the threadpool. Any attempts to use + /// `join`, `scope`, or parallel iterators will then operate within that + /// threadpool. + /// + /// Broadcasts are executed on each thread after they have exhausted their + /// local work queue, before they attempt work-stealing from other threads. + /// The goal of that strategy is to run everywhere in a timely manner + /// *without* being too disruptive to current work. There may be alternative + /// broadcast styles added in the future for more or less aggressive + /// injection, if the need arises. + /// + /// # Warning: thread-local data + /// + /// Because `op` is executing within the Rayon thread-pool, + /// thread-local data from the current thread will not be + /// accessible. + /// + /// # Panics + /// + /// If `op` should panic on one or more threads, exactly one panic + /// will be propagated, only after all threads have completed + /// (or panicked) their own `op`. + /// + /// # Examples + /// + /// ``` + /// # use rayon_core as rayon; + /// use std::sync::atomic::{AtomicUsize, Ordering}; + /// + /// fn main() { + /// let pool = rayon::ThreadPoolBuilder::new().num_threads(5).build().unwrap(); + /// + /// // The argument gives context, including the index of each thread. + /// let v: Vec<usize> = pool.broadcast(|ctx| ctx.index() * ctx.index()); + /// assert_eq!(v, &[0, 1, 4, 9, 16]); + /// + /// // The closure can reference the local stack + /// let count = AtomicUsize::new(0); + /// pool.broadcast(|_| count.fetch_add(1, Ordering::Relaxed)); + /// assert_eq!(count.into_inner(), 5); + /// } + /// ``` + pub fn broadcast<OP, R>(&self, op: OP) -> Vec<R> + where + OP: Fn(BroadcastContext<'_>) -> R + Sync, + R: Send, + { + // We assert that `self.registry` has not terminated. + unsafe { broadcast::broadcast_in(op, &self.registry) } + } + /// Returns the (current) number of threads in the thread pool. /// /// # Future compatibility note @@ -277,6 +327,18 @@ impl ThreadPool { // We assert that `self.registry` has not terminated. unsafe { spawn::spawn_fifo_in(op, &self.registry) } } + + /// Spawns an asynchronous task on every thread in this thread-pool. This task + /// will run in the implicit, global scope, which means that it may outlast the + /// current stack frame -- therefore, it cannot capture any references onto the + /// stack (you will likely need a `move` closure). + pub fn spawn_broadcast<OP>(&self, op: OP) + where + OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static, + { + // We assert that `self.registry` has not terminated. + unsafe { broadcast::spawn_broadcast_in(op, &self.registry) } + } } impl Drop for ThreadPool { diff --git a/vendor/rayon-core/src/thread_pool/test.rs b/vendor/rayon-core/src/thread_pool/test.rs index 8de65a5e4..ac750a6dc 100644 --- a/vendor/rayon-core/src/thread_pool/test.rs +++ b/vendor/rayon-core/src/thread_pool/test.rs @@ -4,8 +4,6 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::channel; use std::sync::{Arc, Mutex}; -#[allow(deprecated)] -use crate::Configuration; use crate::{join, Scope, ScopeFifo, ThreadPool, ThreadPoolBuilder}; #[test] @@ -197,7 +195,7 @@ fn mutual_install_sleepy() { #[test] #[allow(deprecated)] fn check_thread_pool_new() { - let pool = ThreadPool::new(Configuration::new().num_threads(22)).unwrap(); + let pool = ThreadPool::new(crate::Configuration::new().num_threads(22)).unwrap(); assert_eq!(pool.current_num_threads(), 22); } diff --git a/vendor/rayon-core/tests/double_init_fail.rs b/vendor/rayon-core/tests/double_init_fail.rs index ea06bf0e1..b3ddbeb88 100644 --- a/vendor/rayon-core/tests/double_init_fail.rs +++ b/vendor/rayon-core/tests/double_init_fail.rs @@ -4,7 +4,7 @@ use std::error::Error; #[test] fn double_init_fail() { let result1 = ThreadPoolBuilder::new().build_global(); - assert_eq!(result1.unwrap(), ()); + assert!(result1.is_ok()); let err = ThreadPoolBuilder::new().build_global().unwrap_err(); assert!(err.source().is_none()); assert_eq!( diff --git a/vendor/rayon/.cargo-checksum.json b/vendor/rayon/.cargo-checksum.json index bafaf7aa1..24bf4ae59 100644 --- a/vendor/rayon/.cargo-checksum.json +++ b/vendor/rayon/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.lock":"3f9423e7186b573e3632630f65eadbb0fdac3ba6583cdd2e2a97e1832000e3a7","Cargo.toml":"ede262e8b6de1196f9b1d1586930af020e69c4d2ab08e01c85960a6fe0a76f79","FAQ.md":"e963b051f6295a2944ff5abec368c7da914b913e21049978c2ef0017294abf8f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"2158e2d42c6b42c357f494c87218ac5b1cef8fff8d14bebd37c5968475208b90","RELEASES.md":"7ce306bade407f48d882eeef320f4e4500534d9f4eb03b1ad020236080a2799b","build.rs":"72293313a5e41d4828418c49453c2001eb76c4adee600b6442ef18bed4ed1baf","examples/README.md":"537e6fe9cf696fd4ada9c08bf31055ed6e366ed65668a523e7c5fde77f97c8d3","examples/cpu_monitor.rs":"cc21a2635059ab2d86622d86508ce360c105417522b7bd1f8e0b3ac845ed484a","src/array.rs":"ba8f5da438ddda58f71d59fcd1bfb8c2aa3ff30038ad304019c384e7f899d577","src/collections/binary_heap.rs":"58e2590ff52fa2cfe7b5797fdc37902d0c111cca844aac21a4024add2f28a8db","src/collections/btree_map.rs":"d3094ed5c54620f81a86133f52e74164bae9f0137745eb66e6d31db2e942bcab","src/collections/btree_set.rs":"7de12e388d36cb2f8672bc3b68aed5b44d047c9f5fe262a7260584634299480f","src/collections/hash_map.rs":"cdaf1aa3bedf9bde591fcb323d64bee9366feb35fee6886bedb5fec8d0018564","src/collections/hash_set.rs":"685690108fc20eca2cf346e74e48d6c751f5ceb6028996366d49f1f1ad6051e0","src/collections/linked_list.rs":"bef7f32da49b55db76cfefa0afa4789a6979e08a69427e49bab2874967163fef","src/collections/mod.rs":"183017c54dd7926115de4814f1818c85fbbecc913de4f408094f7a4bf6d8443b","src/collections/vec_deque.rs":"d14aa4edc858cd3469fff3597fc35ab83c27f3bdf66ede06d1dd25021f383109","src/compile_fail/cannot_collect_filtermap_data.rs":"6a141076c14f95e31bed3433d531bc05d806eed9e0018d1b21420d7ab2fc7eb9","src/compile_fail/cannot_zip_filtered_data.rs":"a28cfb3d00b8d277bfa77a10ca132f972e8f100080ef602fdd3c6fd36ad2a156","src/compile_fail/cell_par_iter.rs":"4f076862d9c66ed42a642a5be97116ca5982608ab76816a8f8305182bf463e9e","src/compile_fail/mod.rs":"2c346e4b52941fe0ac2667eeb753c0c21a1f998a544bb9d9167f200caba0a7bb","src/compile_fail/must_use.rs":"eb0c35acd5ba4c47ddd06950190ef2bcbeac3a201eec67b2b01781d0c1a251c3","src/compile_fail/no_send_par_iter.rs":"e78cd466a61081a0738f63b4e74249e40c37b95240e47e3faeab6ffdb6a8f14c","src/compile_fail/rc_par_iter.rs":"0faf3d26a665c3e2acc2f2f1d66ee234e561d24442efa4980a5e946e1cb2eba3","src/delegate.rs":"aad2a11998240fb7dd96bd054b588cac469df3b716b8dffb05239102b6507d05","src/iter/chain.rs":"f82a25577ca36bac93b5a13e75dcd70e8cee381b9baa5993dd645f0714fb9eb6","src/iter/chunks.rs":"8ab345783cb7412438eed33264d7db79873801784af7dab25291c349c678085f","src/iter/cloned.rs":"35e1c864f99f7bc93c258c4976d15ccfc1d04df969dc878fd03d35f6799377f7","src/iter/collect/consumer.rs":"5f9728fdf2db728a3ea37849c2fc43c417b221e580860be4dfc6cab526e57f8e","src/iter/collect/mod.rs":"ede28d59713c3291709a842cd54b17760008f6854a3982404eca973bdc3d2f23","src/iter/collect/test.rs":"975875022cf45f9a991040c60f3ed1f9df3805e27f64bbca5b446774793eddef","src/iter/copied.rs":"1a3457f3b0fb020593049b8b1f1be2f7a6684c2fcc66c02c911cb14e0a1943d7","src/iter/empty.rs":"3cb2d05721aab1a4d9e9c5813473e1646116c1ea570e26d9ac81e083688a0b7d","src/iter/enumerate.rs":"3204255723a93b3275cf0f208939de8960b13a9b13b8c2ba6b664e65da21cd87","src/iter/extend.rs":"6b93885d0bce6b1e01d9e220083e421436142b003dbe21f914dcf6b08abe7f10","src/iter/filter.rs":"c8ceea2f71afd1ffc7c713d8683e337e2c4bc3327f47d25116039ab7d950376f","src/iter/filter_map.rs":"18b2fa2d5119297ed6218e353ebb50e7cf4c853e76b9feffd2f332a885d8811d","src/iter/find.rs":"73b11b97eae7234099a05b5f59c937fe488e6a8574b9c9e4e852a7fa86341117","src/iter/find_first_last/mod.rs":"fa7d7692d81ecdbecb178606ad3b1b00c80e5e4159c57d34929b012b0bea0c82","src/iter/find_first_last/test.rs":"2052eb8b87c5a0a0d49a76c83d9d74f81be18aad52ceb1b06d7e209f4fefba94","src/iter/flat_map.rs":"4db54dcda5f1f916497d0162268e6cd554478bc7ea0190709cc7c73941a0e20f","src/iter/flat_map_iter.rs":"81886d1d71f4991963ec9b6d767d9ef391c9e84807d27f6135cd92a451dc1b32","src/iter/flatten.rs":"93407a8f44f4a265f47d7fe568508d6ef922597c4ca4558e8945cf1aacdd6b30","src/iter/flatten_iter.rs":"23cf3ddc25b6cad117932c4bac2e8b945c6b56626730fd3b1787f233495d15e6","src/iter/fold.rs":"874259b408d7f8cdc376d34276d37c1837950c035ff780de8281d1edf65ded9f","src/iter/for_each.rs":"7af0e21ed8479eec65831d1409f61a88d45a31764f2385ec759eda1a46d388b2","src/iter/from_par_iter.rs":"9439b1ae01db2c7545d6416108700dfbafcff3f584e81704cf985ab1d986b660","src/iter/inspect.rs":"d4f5c031e4a79c01b8439b5e3c78b637ecb4bcf191c8d98ec9f31a0b51977abc","src/iter/interleave.rs":"dcda8d2bd46de25227ac88243ff6ca97fcf1dbb89f935b651fd04c1ecf1abe8a","src/iter/interleave_shortest.rs":"a2b1f31ea4cb29f4761d3724feddcf5a96e1f21fd623f95c85a8659294a6745a","src/iter/intersperse.rs":"6b5d3d826ed3499ba78f0ff07468d96a0e104c7ee142a2ced6be8143b43241a5","src/iter/len.rs":"1d890dffb912134402c4778b1635af713df23df8bd2a98890209926a936d8407","src/iter/map.rs":"66e6db399de12327fec29d069462347dd16fd96d450b121ba8227e32e51552d1","src/iter/map_with.rs":"f83950016bb02addecec049fda73663861c80232477a7b89b7e8718291a4b481","src/iter/mod.rs":"6471fd96eea73c025f76abc00562c848fd216e10e736f49773e7d82cbce53ae9","src/iter/multizip.rs":"10ec107f6673c9bc6d1d611e11b716c37e8601ab2f4257a460c4bc4962771347","src/iter/noop.rs":"5be6332ddfbb8fdbae1ffdb00983950a8b37a295bcb58e9a265b33806ee504e6","src/iter/once.rs":"fcebffc374dcdd206d13311dcc2e7d7a04da5687658b2f3ec3409f03ed12774b","src/iter/panic_fuse.rs":"2a4d43fa4e717629de7f69eb180f13db90ef95004975cfa20dcfaacc80435015","src/iter/par_bridge.rs":"0066e4f2ebec979cf912f27fdccd2a670bc7f387036c9bd3c8c1402ce3692139","src/iter/plumbing/README.md":"d9ae3d57a37af5645b1c79029dd808933279d6853b30163cd0d71ead2a9a5002","src/iter/plumbing/mod.rs":"1156c55a15b651d161f463cb86b2f602f6246a3c7f8a82fb484db12aa6a60091","src/iter/positions.rs":"b7abfb59c12b6cceb5e539e85f9eca836054ae88225e16cfc0ba8e68177c7917","src/iter/product.rs":"da69f4781c2275c4a176432994c3fd80ea1f296afe47b329de61b1d733d990df","src/iter/reduce.rs":"2f5d6e07d7c0de2360505fa5d9198c31fd43ba7e58a6ec40f79edec19319e502","src/iter/repeat.rs":"ed46b17b79d8569f9d67b50585b116ee0293e1d6c17c0dc683c66644f6a58fd5","src/iter/rev.rs":"c4c796d7cb6398e74bef043a080403acccdf70f6a4e74b242e530d1718969b8f","src/iter/skip.rs":"93d54e17316ae15ff3cc30ca7144cb448569b18ea967dd2cd8913ac6f1334390","src/iter/splitter.rs":"0024db04b4430c2a1e8c921cec86af641f612f877f3675b15df0da9122de5f00","src/iter/step_by.rs":"e0e27a6b202e469237631f8a0040b40ac70429c660f6e3c0674bbce3e22537fc","src/iter/sum.rs":"cf11d996507ceba39524a102559b84289e776f8fe5772114e00ae2112b38c47c","src/iter/take.rs":"e47eeca1249553b0dfaf54cd8f99026be68db76b42f1f29e09c07a98c165c50a","src/iter/test.rs":"52ab229c2d8c4d4baf0d0cb439accbced982da088d66c3b404c97ef6bc0e136c","src/iter/try_fold.rs":"de3cee1a5e27086e259d1c189215c8984830ef65c89f75304f400a14158c85b1","src/iter/try_reduce.rs":"7697b2024709546afe9a5f0a21bc8645fdb1096b01fab1e7f7030a5c85c5f8b1","src/iter/try_reduce_with.rs":"2b62233766ba5cf9f13a1f64d3d0508c6b03093c810b1115df6777ff48aa9513","src/iter/unzip.rs":"9a16ea1f3b3019a090b7189f6c42c75beb3537bc849bd4c51093120a907cea6b","src/iter/update.rs":"08a222cf7f8f2f82389ca48d89ecef3a88e205d21ce249f2ba15a4ff85134473","src/iter/while_some.rs":"a514891d7a07031354b48e377c239ff330d0955f184abc57a69d2a193e7fcb45","src/iter/zip.rs":"4d908f75a10b5e9b68d012bbba289f3e5e9d6a9570ce0f56fc1b4f9d96860499","src/iter/zip_eq.rs":"4c18d8f7a78e197a3268c9ef74d16690f8c960407c18bb63dc6905a2fe2bde62","src/lib.rs":"2e1136e6cf10961a335932af1546d3d02765f81d3d5e89fd834e439c99e52286","src/math.rs":"4ca70519f251c479b454760c3ebadc121f4c5db358fe54cd830440cd9c98e19c","src/option.rs":"00979a9bb8f42629f2b956a6cfbd286fc8a41ffbbec85f1b5d0f0da5615dac9c","src/par_either.rs":"afa4b04ba6ea1d37aed2d68eca44d7ba0d1d09ea985c9091540dd8d3c51974f1","src/prelude.rs":"b1af578abff57f9c8a285c39e3793125cf40d9901d0f2a4f0c5f1bb9252a08de","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/range.rs":"93bd821b851d334a365211e14b60e0fc5052a7ee09e9a26ea7dd4f018c9bf7ae","src/range_inclusive.rs":"1f18ee155ab46e7398203163d49b4dfa87135e578de3d80e2641877c5b037126","src/result.rs":"0656f0000efcea10e571df90247925dfd00a0c2194043fcbc009711fb2f7af02","src/slice/chunks.rs":"ae41c3465b0f252c8642fe39751cfabfcca6a9de4cd4bb594ee4a7f86dde880b","src/slice/mergesort.rs":"bc49ec902eab794fb474cf8444486011cffc549897ad14212fe963caffd43460","src/slice/mod.rs":"6eb3ec907365ed5d20cef0e7a1e6d99596ac217bdfd623ff26f2c773b44ac931","src/slice/quicksort.rs":"5ffd69f9e27dce6794c838b6044461a5de36214ef86cc044929062c000a1841f","src/slice/rchunks.rs":"811cdad43cd83a21c5190de9c77eee81da4a47d19a8a9160f132b961768377c5","src/slice/test.rs":"6d0a1cbe0547fb4a16c2beb99f0473d7fe42af69a67ff16ab8a9f61d0442fcb9","src/split_producer.rs":"2b143e16bc6540792f861e215a86cfea7f4ee500d4faca2476d4165619eac90d","src/str.rs":"19f2184cb1f8cbc98f953b1499e3d7ec9e1235fde5a03ad7e6a6ebf6ef5f90f3","src/string.rs":"6691dd31264bd93a0528fc584585415c12f56cfb4baebbfd31ea2f1b21550f77","src/vec.rs":"aece662a957ecaee9a313b76411fbb2418f88795c162b5e00fc41f732c20a9fa","tests/chars.rs":"5a2bef1cd8a7d1740a4e5403830da7bbdd584e97d602a07645c4986ee34c2ad3","tests/clones.rs":"8e48be01dd846c35d996c758be6a38e18763e0e42bc8f34b4f98845ea7bb0abc","tests/collect.rs":"27173f932d5c65932ad63c215c561ecf06fcbeb7253a7bb175b819e0a40107aa","tests/cross-pool.rs":"103c121c8684eef0868e3982219e406500009c26d7602167f5a514b1dfd3b4cc","tests/debug.rs":"6b2519764980232cd6247d2acef1c1346c7fb7b51470449242fa7f9f22fc0b52","tests/intersperse.rs":"bda4fb2179086e32c77c8293b9bb85d55509c282441837ba1849c2d3aa3186a7","tests/issue671-unzip.rs":"d5eb38d8a6d8f66fdf1c40293abbf58f3ac42b5acfc5dca62b02c7ace5bfc1a4","tests/issue671.rs":"52914cac517074deaedcb81bd76b867f0b99cc7b65c3e01cfe12dc9fe38c0266","tests/iter_panic.rs":"376faac33739e3479b5eb744bb2c810c27f8fdda5eeb9ad96d8b93619bf11d1c","tests/named-threads.rs":"48dd0fa0de13b4554dfc1fc0adaee093e19df8b1fc601f5b9b4f15b1fc705249","tests/octillion.rs":"65e12a22f5bc6e22316b93c57c82c2556ef8a5afd4d846a6431ce8c0499ce804","tests/producer_split_at.rs":"fbb28da59e85e4c253cc314f35f113ced8db2981ceda9977145af540f9996837","tests/sort-panic-safe.rs":"290a37a1cf7e297e622fc84caa5c7c3d50e83643a3c4f67a05cf2e1f7d6f3fc0","tests/str.rs":"49059384999be57994841652718cc048389380741be5c493423f8bd2206e4453"},"package":"bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"}
\ No newline at end of file +{"files":{"Cargo.toml":"29c768a031b0c4c2b8012af25cee42f89d5e6d7bd89ec8cf8df4972420a55cc3","FAQ.md":"e963b051f6295a2944ff5abec368c7da914b913e21049978c2ef0017294abf8f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"d972f524a7de70888a57ed63625272d4bbc24ecbdffcdb7ba8d3d520e60ab79e","RELEASES.md":"bb8dae2b0c1ec1b6c8ecd142097b4a3f11011397f7d327024936c33678851066","src/array.rs":"edd4442a74c08128284a242a6874686b25d539e8a57886fef82216e5ff31f851","src/collections/binary_heap.rs":"58e2590ff52fa2cfe7b5797fdc37902d0c111cca844aac21a4024add2f28a8db","src/collections/btree_map.rs":"d3094ed5c54620f81a86133f52e74164bae9f0137745eb66e6d31db2e942bcab","src/collections/btree_set.rs":"7de12e388d36cb2f8672bc3b68aed5b44d047c9f5fe262a7260584634299480f","src/collections/hash_map.rs":"cdaf1aa3bedf9bde591fcb323d64bee9366feb35fee6886bedb5fec8d0018564","src/collections/hash_set.rs":"685690108fc20eca2cf346e74e48d6c751f5ceb6028996366d49f1f1ad6051e0","src/collections/linked_list.rs":"bef7f32da49b55db76cfefa0afa4789a6979e08a69427e49bab2874967163fef","src/collections/mod.rs":"3978222720a2df20be7fd0856d8515b6f9fa40f6556662bd3c0726b1392970ca","src/collections/vec_deque.rs":"d14aa4edc858cd3469fff3597fc35ab83c27f3bdf66ede06d1dd25021f383109","src/compile_fail/cannot_collect_filtermap_data.rs":"f76e6727ae8bd0dc8fff5f4a79df3fc598daf5d7371bdf8b2e730fba4ba82719","src/compile_fail/cannot_zip_filtered_data.rs":"3588fcf72e804ea867ea525b6dfa7a3d45fe14e28088e849fa9ddb029acc8a7a","src/compile_fail/cell_par_iter.rs":"ebf8804993c103f9d8228aba0bb2a5f0aadb957de9f1eb59cf546dbace285201","src/compile_fail/mod.rs":"2c346e4b52941fe0ac2667eeb753c0c21a1f998a544bb9d9167f200caba0a7bb","src/compile_fail/must_use.rs":"42ae57ed7cb909fad8d079ce6e3742a92ca7f72a9cc209b149d1d88df568d757","src/compile_fail/no_send_par_iter.rs":"b241446439c659f35060df12ba91590ea4267f373ddc688e4ffc203321db24b3","src/compile_fail/rc_par_iter.rs":"938776b08612e35c85b99962024d54af5a8c87d45a050a76375d16ef6fe4299f","src/delegate.rs":"aad2a11998240fb7dd96bd054b588cac469df3b716b8dffb05239102b6507d05","src/iter/chain.rs":"f82a25577ca36bac93b5a13e75dcd70e8cee381b9baa5993dd645f0714fb9eb6","src/iter/chunks.rs":"9b901441bd8684782d4e50bf24c261bdf3392f576e7ab25b2b83be2fc9361545","src/iter/cloned.rs":"35e1c864f99f7bc93c258c4976d15ccfc1d04df969dc878fd03d35f6799377f7","src/iter/collect/consumer.rs":"5f9728fdf2db728a3ea37849c2fc43c417b221e580860be4dfc6cab526e57f8e","src/iter/collect/mod.rs":"ede28d59713c3291709a842cd54b17760008f6854a3982404eca973bdc3d2f23","src/iter/collect/test.rs":"975875022cf45f9a991040c60f3ed1f9df3805e27f64bbca5b446774793eddef","src/iter/copied.rs":"1a3457f3b0fb020593049b8b1f1be2f7a6684c2fcc66c02c911cb14e0a1943d7","src/iter/empty.rs":"3cb2d05721aab1a4d9e9c5813473e1646116c1ea570e26d9ac81e083688a0b7d","src/iter/enumerate.rs":"3204255723a93b3275cf0f208939de8960b13a9b13b8c2ba6b664e65da21cd87","src/iter/extend.rs":"6b93885d0bce6b1e01d9e220083e421436142b003dbe21f914dcf6b08abe7f10","src/iter/filter.rs":"e48f317ee4d66dea6f19ac2607c6f764d20c023d847b66c6c01826e6a46f96ab","src/iter/filter_map.rs":"2530b726b27fe3a678a34722b1baf8e223a65a0770fa8ed5dca13786ea454580","src/iter/find.rs":"896ddb05b2fa7368462e0ff2a73982ced5f93266c0e0e8c27bb3fc4ec737af21","src/iter/find_first_last/mod.rs":"fa7d7692d81ecdbecb178606ad3b1b00c80e5e4159c57d34929b012b0bea0c82","src/iter/find_first_last/test.rs":"2052eb8b87c5a0a0d49a76c83d9d74f81be18aad52ceb1b06d7e209f4fefba94","src/iter/flat_map.rs":"4db54dcda5f1f916497d0162268e6cd554478bc7ea0190709cc7c73941a0e20f","src/iter/flat_map_iter.rs":"81886d1d71f4991963ec9b6d767d9ef391c9e84807d27f6135cd92a451dc1b32","src/iter/flatten.rs":"93407a8f44f4a265f47d7fe568508d6ef922597c4ca4558e8945cf1aacdd6b30","src/iter/flatten_iter.rs":"23cf3ddc25b6cad117932c4bac2e8b945c6b56626730fd3b1787f233495d15e6","src/iter/fold.rs":"874259b408d7f8cdc376d34276d37c1837950c035ff780de8281d1edf65ded9f","src/iter/fold_chunks.rs":"78c267cc341fa71206a587b548480038a7a9bbb29d341b43733515b34e4cec48","src/iter/fold_chunks_with.rs":"fc3a49dd6a2027ec8e0c78e459ed80da1185b365909694bf1395af12b22648a8","src/iter/for_each.rs":"7af0e21ed8479eec65831d1409f61a88d45a31764f2385ec759eda1a46d388b2","src/iter/from_par_iter.rs":"9439b1ae01db2c7545d6416108700dfbafcff3f584e81704cf985ab1d986b660","src/iter/inspect.rs":"d502b6e435a44f34ba49dfe46aa809a1bad3dbaefa048540a98e3026437b1016","src/iter/interleave.rs":"3c6d82fe13b52e2ce5e1b3dba93c47f479ff44d232059cd88523b422c51dea96","src/iter/interleave_shortest.rs":"a2b1f31ea4cb29f4761d3724feddcf5a96e1f21fd623f95c85a8659294a6745a","src/iter/intersperse.rs":"6b5d3d826ed3499ba78f0ff07468d96a0e104c7ee142a2ced6be8143b43241a5","src/iter/len.rs":"1d890dffb912134402c4778b1635af713df23df8bd2a98890209926a936d8407","src/iter/map.rs":"f778f1bd0a71c962375d2ce886b40ac365afed4a032e2b9dd6c385712d3d75eb","src/iter/map_with.rs":"f83950016bb02addecec049fda73663861c80232477a7b89b7e8718291a4b481","src/iter/mod.rs":"e54fbede51a3a93c338a8d37edb47f78895f8f9a3b0760ad92ea5f4c3de09665","src/iter/multizip.rs":"10ec107f6673c9bc6d1d611e11b716c37e8601ab2f4257a460c4bc4962771347","src/iter/noop.rs":"5be6332ddfbb8fdbae1ffdb00983950a8b37a295bcb58e9a265b33806ee504e6","src/iter/once.rs":"fcebffc374dcdd206d13311dcc2e7d7a04da5687658b2f3ec3409f03ed12774b","src/iter/panic_fuse.rs":"2a4d43fa4e717629de7f69eb180f13db90ef95004975cfa20dcfaacc80435015","src/iter/par_bridge.rs":"0066e4f2ebec979cf912f27fdccd2a670bc7f387036c9bd3c8c1402ce3692139","src/iter/plumbing/README.md":"28050be91cbaf1932e65607939722bf9a0563d25d98a4e000c3a5a320488e4aa","src/iter/plumbing/mod.rs":"1156c55a15b651d161f463cb86b2f602f6246a3c7f8a82fb484db12aa6a60091","src/iter/positions.rs":"b7abfb59c12b6cceb5e539e85f9eca836054ae88225e16cfc0ba8e68177c7917","src/iter/product.rs":"da69f4781c2275c4a176432994c3fd80ea1f296afe47b329de61b1d733d990df","src/iter/reduce.rs":"2f5d6e07d7c0de2360505fa5d9198c31fd43ba7e58a6ec40f79edec19319e502","src/iter/repeat.rs":"ed46b17b79d8569f9d67b50585b116ee0293e1d6c17c0dc683c66644f6a58fd5","src/iter/rev.rs":"c4c796d7cb6398e74bef043a080403acccdf70f6a4e74b242e530d1718969b8f","src/iter/skip.rs":"93d54e17316ae15ff3cc30ca7144cb448569b18ea967dd2cd8913ac6f1334390","src/iter/splitter.rs":"0024db04b4430c2a1e8c921cec86af641f612f877f3675b15df0da9122de5f00","src/iter/step_by.rs":"be7abe2c2fba252a1b69c8cf18adfe510036c30f8ee2994404c18ae15dde317e","src/iter/sum.rs":"cf11d996507ceba39524a102559b84289e776f8fe5772114e00ae2112b38c47c","src/iter/take.rs":"e47eeca1249553b0dfaf54cd8f99026be68db76b42f1f29e09c07a98c165c50a","src/iter/test.rs":"dad5c78aa8bbd7d62cf0d76194f3c02d8f12236c5f90897f3f97f884ac1b5171","src/iter/try_fold.rs":"d4f40a00995273b8803031da4a4b139a5f462a174ef1d3c8ba54524b47ab8180","src/iter/try_reduce.rs":"12317a649f777e76e6ae610d205104d7946fbe45804fbf1caa0843118531baed","src/iter/try_reduce_with.rs":"9171563fc22110d7a359f19de7ca66a6823d8f712099d05d01560795781fdeec","src/iter/unzip.rs":"9a16ea1f3b3019a090b7189f6c42c75beb3537bc849bd4c51093120a907cea6b","src/iter/update.rs":"0362185a002cdda0e73b13237017ddc3d5e72390bba6cb2e2f021e947ed861dc","src/iter/while_some.rs":"a514891d7a07031354b48e377c239ff330d0955f184abc57a69d2a193e7fcb45","src/iter/zip.rs":"4d908f75a10b5e9b68d012bbba289f3e5e9d6a9570ce0f56fc1b4f9d96860499","src/iter/zip_eq.rs":"4c18d8f7a78e197a3268c9ef74d16690f8c960407c18bb63dc6905a2fe2bde62","src/lib.rs":"3607c5d8efce43560fff74dfa66668c1d85fd12f0ffd60aa5c7c545e8c8e77fa","src/math.rs":"040e82a4ba7a6680eb65b65f4d1fc3dc477d902855d8651105b138ae2e71c8e8","src/option.rs":"00979a9bb8f42629f2b956a6cfbd286fc8a41ffbbec85f1b5d0f0da5615dac9c","src/par_either.rs":"afa4b04ba6ea1d37aed2d68eca44d7ba0d1d09ea985c9091540dd8d3c51974f1","src/prelude.rs":"b1af578abff57f9c8a285c39e3793125cf40d9901d0f2a4f0c5f1bb9252a08de","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/range.rs":"93bd821b851d334a365211e14b60e0fc5052a7ee09e9a26ea7dd4f018c9bf7ae","src/range_inclusive.rs":"1f18ee155ab46e7398203163d49b4dfa87135e578de3d80e2641877c5b037126","src/result.rs":"0656f0000efcea10e571df90247925dfd00a0c2194043fcbc009711fb2f7af02","src/slice/chunks.rs":"2bf07a3522381e7747e40f787727747b62fbe1f1504eac6c383f0608a335ec91","src/slice/mergesort.rs":"effe59ecc40b330c364a3da868182b72b487025d9ba0256079f8a284b85a05ef","src/slice/mod.rs":"d293c9105edc3e51b11f873ac816f28232dd708120901ce3a518e03d5b748bcf","src/slice/quicksort.rs":"355506e39eac03b18cf35a6fa01d8f126267e01736e03c85f22414ebf894a9be","src/slice/rchunks.rs":"23229976840da07e8fff6657ca626810ed380682719e4d1f0693ac08839e1b7c","src/slice/test.rs":"fca5e5e6bb5464c9332d14e7d963098ad9a072801ea508ae9eabf5d278b66bb2","src/split_producer.rs":"2b143e16bc6540792f861e215a86cfea7f4ee500d4faca2476d4165619eac90d","src/str.rs":"fe3fca9218fd17a265619551602001addf80f83187b086b3c65b4edd7857abd2","src/string.rs":"6691dd31264bd93a0528fc584585415c12f56cfb4baebbfd31ea2f1b21550f77","src/vec.rs":"c9d2f99d9a3577d57640f52e33c2d8f62b0637a8ec21bbc4aefa51ce12f7059d","tests/chars.rs":"5a2bef1cd8a7d1740a4e5403830da7bbdd584e97d602a07645c4986ee34c2ad3","tests/clones.rs":"8b1bd752d0b39b0722fa30583962940a68c917b2f7dbe6b479da5a3e7d3c5efb","tests/collect.rs":"27173f932d5c65932ad63c215c561ecf06fcbeb7253a7bb175b819e0a40107aa","tests/cross-pool.rs":"103c121c8684eef0868e3982219e406500009c26d7602167f5a514b1dfd3b4cc","tests/debug.rs":"de22193e15ac078a9952e42d255bce0f30ac7f4f69957aa6b0aada0eac146ca0","tests/drain_vec.rs":"305ca40ba41ed3b459a334386cd742c66586d62aadfb624278aabdf10b872a12","tests/intersperse.rs":"bda4fb2179086e32c77c8293b9bb85d55509c282441837ba1849c2d3aa3186a7","tests/issue671-unzip.rs":"d5eb38d8a6d8f66fdf1c40293abbf58f3ac42b5acfc5dca62b02c7ace5bfc1a4","tests/issue671.rs":"52914cac517074deaedcb81bd76b867f0b99cc7b65c3e01cfe12dc9fe38c0266","tests/iter_panic.rs":"61f0c036a2fa555303bf317ac15b4d25f1316a3beb313c8e2fca7f85228450b4","tests/named-threads.rs":"48dd0fa0de13b4554dfc1fc0adaee093e19df8b1fc601f5b9b4f15b1fc705249","tests/octillion.rs":"65e12a22f5bc6e22316b93c57c82c2556ef8a5afd4d846a6431ce8c0499ce804","tests/producer_split_at.rs":"fbb28da59e85e4c253cc314f35f113ced8db2981ceda9977145af540f9996837","tests/sort-panic-safe.rs":"290a37a1cf7e297e622fc84caa5c7c3d50e83643a3c4f67a05cf2e1f7d6f3fc0","tests/str.rs":"49059384999be57994841652718cc048389380741be5c493423f8bd2206e4453"},"package":"1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"}
\ No newline at end of file diff --git a/vendor/rayon/Cargo.lock b/vendor/rayon/Cargo.lock deleted file mode 100644 index 798468bc9..000000000 --- a/vendor/rayon/Cargo.lock +++ /dev/null @@ -1,290 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crossbeam-channel" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "docopt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.137 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.125 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.10.2+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.125 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.125" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.125 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.125 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ppv-lite86 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon" -version = "1.5.3" -dependencies = [ - "autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.137 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-channel 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "regex-syntax 0.6.25 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.137 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-xid" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" - - -[metadata] -"checksum autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -"checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -"checksum crossbeam-channel 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" -"checksum crossbeam-deque 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -"checksum crossbeam-epoch 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" -"checksum crossbeam-utils 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -"checksum docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" -"checksum either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -"checksum getrandom 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -"checksum hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.125 (registry+https://github.com/rust-lang/crates.io-index)" = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" -"checksum memoffset 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -"checksum num_cpus 1.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -"checksum ppv-lite86 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" -"checksum proc-macro2 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" -"checksum quote 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -"checksum rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -"checksum rand_chacha 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -"checksum rand_core 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -"checksum rand_xorshift 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -"checksum rayon-core 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" -"checksum regex 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" -"checksum regex-syntax 0.6.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -"checksum serde 1.0.137 (registry+https://github.com/rust-lang/crates.io-index)" = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" -"checksum serde_derive 1.0.137 (registry+https://github.com/rust-lang/crates.io-index)" = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" -"checksum strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -"checksum syn 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a" -"checksum unicode-xid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" -"checksum wasi 0.10.2+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/vendor/rayon/Cargo.toml b/vendor/rayon/Cargo.toml index b5a6a6c7a..8b1075d7f 100644 --- a/vendor/rayon/Cargo.toml +++ b/vendor/rayon/Cargo.toml @@ -10,9 +10,10 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" +rust-version = "1.56" name = "rayon" -version = "1.5.3" +version = "1.6.0" authors = [ "Niko Matsakis <niko@alum.mit.edu>", "Josh Stone <cuviper@gmail.com>", @@ -45,10 +46,7 @@ version = "1.0" default-features = false [dependencies.rayon-core] -version = "1.9.2" - -[dev-dependencies.docopt] -version = "1" +version = "1.10.0" [dev-dependencies.lazy_static] version = "1" @@ -58,10 +56,3 @@ version = "0.8" [dev-dependencies.rand_xorshift] version = "0.3" - -[dev-dependencies.serde] -version = "1.0.85" -features = ["derive"] - -[build-dependencies.autocfg] -version = "1" diff --git a/vendor/rayon/README.md b/vendor/rayon/README.md index b8156db7c..51d92a626 100644 --- a/vendor/rayon/README.md +++ b/vendor/rayon/README.md @@ -2,7 +2,7 @@ [![Rayon crate](https://img.shields.io/crates/v/rayon.svg)](https://crates.io/crates/rayon) [![Rayon documentation](https://docs.rs/rayon/badge.svg)](https://docs.rs/rayon) -![minimum rustc 1.36](https://img.shields.io/badge/rustc-1.36+-red.svg) +![minimum rustc 1.56](https://img.shields.io/badge/rustc-1.56+-red.svg) [![build status](https://github.com/rayon-rs/rayon/workflows/master/badge.svg)](https://github.com/rayon-rs/rayon/actions) [![Join the chat at https://gitter.im/rayon-rs/Lobby](https://badges.gitter.im/rayon-rs/Lobby.svg)](https://gitter.im/rayon-rs/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -84,7 +84,7 @@ just add: use rayon::prelude::*; ``` -Rayon currently requires `rustc 1.36.0` or greater. +Rayon currently requires `rustc 1.56.0` or greater. ### Usage with WebAssembly @@ -129,5 +129,5 @@ See [the Rayon FAQ][faq]. Rayon is distributed under the terms of both the MIT license and the Apache License (Version 2.0). See [LICENSE-APACHE](LICENSE-APACHE) and -[LICENSE-MIT](LICENSE-MIT) for details. Opening a pull requests is +[LICENSE-MIT](LICENSE-MIT) for details. Opening a pull request is assumed to signal agreement with these licensing terms. diff --git a/vendor/rayon/RELEASES.md b/vendor/rayon/RELEASES.md index e37540fd7..eed3445ee 100644 --- a/vendor/rayon/RELEASES.md +++ b/vendor/rayon/RELEASES.md @@ -1,3 +1,36 @@ +# Release rayon 1.6.0 / rayon-core 1.10.0 (2022-11-18) + +- The minimum supported `rustc` is now 1.56. +- The new `IndexedParallelIterator::fold_chunks` and `fold_chunks_with` methods + work like `ParallelIterator::fold` and `fold_with` with fixed-size chunks of + items. This may be useful for predictable batching performance, without the + allocation overhead of `IndexedParallelIterator::chunks`. +- New "broadcast" methods run a given function on all threads in the pool. + These run at a sort of reduced priority after each thread has exhausted their + local work queue, but before they attempt work-stealing from other threads. + - The global `broadcast` function and `ThreadPool::broadcast` method will + block until completion, returning a `Vec` of all return values. + - The global `spawn_broadcast` function and methods on `ThreadPool`, `Scope`, + and `ScopeFifo` will run detached, without blocking the current thread. +- Panicking methods now use `#[track_caller]` to report the caller's location. +- Fixed a truncated length in `vec::Drain` when given an empty range. + +## Contributors + +Thanks to all of the contributors for this release! + +- @cuviper +- @idanmuze +- @JoeyBF +- @JustForFun88 +- @kianmeng +- @kornelski +- @ritchie46 +- @ryanrussell +- @steffahn +- @TheIronBorn +- @willcrozi + # Release rayon 1.5.3 (2022-05-13) - The new `ParallelSliceMut::par_sort_by_cached_key` is a stable sort that caches diff --git a/vendor/rayon/build.rs b/vendor/rayon/build.rs deleted file mode 100644 index f38f6ffb4..000000000 --- a/vendor/rayon/build.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() { - let ac = autocfg::new(); - if ac.probe_expression("(0..10).step_by(2).rev()") { - autocfg::emit("has_step_by_rev"); - } - if ac.probe_expression("{ fn _foo<const N: usize>() {} }") { - autocfg::emit("has_min_const_generics"); - } - if ac.probe_path("std::ops::ControlFlow") { - autocfg::emit("has_control_flow"); - } -} diff --git a/vendor/rayon/examples/README.md b/vendor/rayon/examples/README.md deleted file mode 100644 index ec08a4df8..000000000 --- a/vendor/rayon/examples/README.md +++ /dev/null @@ -1,3 +0,0 @@ -We use this directory for interactive tests that can't be run in an -automatic fashion. For examples of how to use Rayon, or benchmarks, -see `rayon-demo`. diff --git a/vendor/rayon/examples/cpu_monitor.rs b/vendor/rayon/examples/cpu_monitor.rs deleted file mode 100644 index bbe13164a..000000000 --- a/vendor/rayon/examples/cpu_monitor.rs +++ /dev/null @@ -1,81 +0,0 @@ -use docopt::Docopt; -use std::io; -use std::process; - -const USAGE: &str = " -Usage: cpu_monitor [options] <scenario> - cpu_monitor --help - -A test for monitoring how much CPU usage Rayon consumes under various -scenarios. This test is intended to be executed interactively, like so: - - cargo run --example cpu_monitor -- tasks_ended - -The list of scenarios you can try are as follows: - -- tasks_ended: after all tasks have finished, go to sleep -- task_stall_root: a root task stalls for a very long time -- task_stall_scope: a task in a scope stalls for a very long time - -Options: - -h, --help Show this message. - -d N, --depth N Control how hard the dummy task works [default: 27] -"; - -#[derive(serde::Deserialize)] -pub struct Args { - arg_scenario: String, - flag_depth: usize, -} - -fn main() { - let args: &Args = &Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); - - match &args.arg_scenario[..] { - "tasks_ended" => tasks_ended(args), - "task_stall_root" => task_stall_root(args), - "task_stall_scope" => task_stall_scope(args), - _ => { - println!("unknown scenario: `{}`", args.arg_scenario); - println!("try --help"); - process::exit(1); - } - } -} - -fn wait_for_user() { - let mut input = String::new(); - io::stdin().read_line(&mut input).unwrap(); -} - -fn task(args: &Args) { - fn join_recursively(n: usize) { - if n == 0 { - return; - } - rayon::join(|| join_recursively(n - 1), || join_recursively(n - 1)); - } - - println!("Starting heavy work at depth {}...wait.", args.flag_depth); - join_recursively(args.flag_depth); - println!("Heavy work done; check top. You should see CPU usage drop to zero soon."); - println!("Press <enter> to quit..."); -} - -fn tasks_ended(args: &Args) { - task(args); - wait_for_user(); -} - -fn task_stall_root(args: &Args) { - rayon::join(|| task(args), wait_for_user); -} - -fn task_stall_scope(args: &Args) { - rayon::scope(|scope| { - scope.spawn(move |_| task(args)); - scope.spawn(move |_| wait_for_user()); - }); -} diff --git a/vendor/rayon/src/array.rs b/vendor/rayon/src/array.rs index c9bd8bd05..937bebf3b 100644 --- a/vendor/rayon/src/array.rs +++ b/vendor/rayon/src/array.rs @@ -1,11 +1,8 @@ -#![cfg(has_min_const_generics)] //! Parallel iterator types for [arrays] (`[T; N]`) //! //! You will rarely need to interact with this module directly unless you need //! to name one of the iterator types. //! -//! Everything in this module requires const generics, stabilized in Rust 1.51. -//! //! [arrays]: https://doc.rust-lang.org/std/primitive.array.html use crate::iter::plumbing::*; @@ -14,7 +11,6 @@ use crate::slice::{Iter, IterMut}; use crate::vec::DrainProducer; use std::mem::ManuallyDrop; -/// This implementation requires const generics, stabilized in Rust 1.51. impl<'data, T: Sync + 'data, const N: usize> IntoParallelIterator for &'data [T; N] { type Item = &'data T; type Iter = Iter<'data, T>; @@ -24,7 +20,6 @@ impl<'data, T: Sync + 'data, const N: usize> IntoParallelIterator for &'data [T; } } -/// This implementation requires const generics, stabilized in Rust 1.51. impl<'data, T: Send + 'data, const N: usize> IntoParallelIterator for &'data mut [T; N] { type Item = &'data mut T; type Iter = IterMut<'data, T>; @@ -34,7 +29,6 @@ impl<'data, T: Send + 'data, const N: usize> IntoParallelIterator for &'data mut } } -/// This implementation requires const generics, stabilized in Rust 1.51. impl<T: Send, const N: usize> IntoParallelIterator for [T; N] { type Item = T; type Iter = IntoIter<T, N>; diff --git a/vendor/rayon/src/collections/mod.rs b/vendor/rayon/src/collections/mod.rs index d9b7988da..3c99f32c4 100644 --- a/vendor/rayon/src/collections/mod.rs +++ b/vendor/rayon/src/collections/mod.rs @@ -56,7 +56,7 @@ mod drain_guard { pub(super) fn new(collection: &'a mut C) -> Self { Self { // Temporarily steal the inner `Vec` so we can drain in place. - vec: Vec::from(mem::replace(collection, C::default())), + vec: Vec::from(mem::take(collection)), collection, } } @@ -65,7 +65,7 @@ mod drain_guard { impl<'a, T, C: From<Vec<T>>> Drop for DrainGuard<'a, T, C> { fn drop(&mut self) { // Restore the collection from the `Vec` with its original capacity. - *self.collection = C::from(mem::replace(&mut self.vec, Vec::new())); + *self.collection = C::from(mem::take(&mut self.vec)); } } diff --git a/vendor/rayon/src/compile_fail/cannot_collect_filtermap_data.rs b/vendor/rayon/src/compile_fail/cannot_collect_filtermap_data.rs index 65ff87532..bb62ce02f 100644 --- a/vendor/rayon/src/compile_fail/cannot_collect_filtermap_data.rs +++ b/vendor/rayon/src/compile_fail/cannot_collect_filtermap_data.rs @@ -5,12 +5,10 @@ use rayon::prelude::*; // zip requires data of exact size, but filter yields only bounded // size, so check that we cannot apply it. -fn main() { - let a: Vec<usize> = (0..1024).collect(); - let mut v = vec![]; - a.par_iter() - .filter_map(|&x| Some(x as f32)) - .collect_into_vec(&mut v); //~ ERROR no method -} +let a: Vec<usize> = (0..1024).collect(); +let mut v = vec![]; +a.par_iter() + .filter_map(|&x| Some(x as f32)) + .collect_into_vec(&mut v); //~ ERROR no method ``` */ diff --git a/vendor/rayon/src/compile_fail/cannot_zip_filtered_data.rs b/vendor/rayon/src/compile_fail/cannot_zip_filtered_data.rs index de43fca57..54fd50de1 100644 --- a/vendor/rayon/src/compile_fail/cannot_zip_filtered_data.rs +++ b/vendor/rayon/src/compile_fail/cannot_zip_filtered_data.rs @@ -5,12 +5,10 @@ use rayon::prelude::*; // zip requires data of exact size, but filter yields only bounded // size, so check that we cannot apply it. -fn main() { - let mut a: Vec<usize> = (0..1024).rev().collect(); - let b: Vec<usize> = (0..1024).collect(); +let mut a: Vec<usize> = (0..1024).rev().collect(); +let b: Vec<usize> = (0..1024).collect(); - a.par_iter() - .zip(b.par_iter().filter(|&&x| x > 3)); //~ ERROR -} +a.par_iter() + .zip(b.par_iter().filter(|&&x| x > 3)); //~ ERROR ``` */ diff --git a/vendor/rayon/src/compile_fail/cell_par_iter.rs b/vendor/rayon/src/compile_fail/cell_par_iter.rs index 4af04b124..98a1cf96e 100644 --- a/vendor/rayon/src/compile_fail/cell_par_iter.rs +++ b/vendor/rayon/src/compile_fail/cell_par_iter.rs @@ -5,11 +5,9 @@ use rayon::prelude::*; use std::cell::Cell; -fn main() { - let c = Cell::new(42_i32); - (0_i32..1024).into_par_iter() - .map(|_| c.get()) //~ ERROR E0277 - .min(); -} +let c = Cell::new(42_i32); +(0_i32..1024).into_par_iter() + .map(|_| c.get()) //~ ERROR E0277 + .min(); ``` */ diff --git a/vendor/rayon/src/compile_fail/must_use.rs b/vendor/rayon/src/compile_fail/must_use.rs index ac50a62f3..b4b3d771c 100644 --- a/vendor/rayon/src/compile_fail/must_use.rs +++ b/vendor/rayon/src/compile_fail/must_use.rs @@ -33,6 +33,8 @@ must_use! { step_by /** v.par_iter().step_by(2); */ chain /** v.par_iter().chain(&v); */ chunks /** v.par_iter().chunks(2); */ + fold_chunks /** v.par_iter().fold_chunks(2, || 0, |x, _| x); */ + fold_chunks_with /** v.par_iter().fold_chunks_with(2, 0, |x, _| x); */ cloned /** v.par_iter().cloned(); */ copied /** v.par_iter().copied(); */ enumerate /** v.par_iter().enumerate(); */ diff --git a/vendor/rayon/src/compile_fail/no_send_par_iter.rs b/vendor/rayon/src/compile_fail/no_send_par_iter.rs index 1362c9809..7573c0346 100644 --- a/vendor/rayon/src/compile_fail/no_send_par_iter.rs +++ b/vendor/rayon/src/compile_fail/no_send_par_iter.rs @@ -10,13 +10,11 @@ struct NoSend(*const ()); unsafe impl Sync for NoSend {} -fn main() { - let x = Some(NoSend(null())); +let x = Some(NoSend(null())); - x.par_iter() - .map(|&x| x) //~ ERROR - .count(); //~ ERROR -} +x.par_iter() + .map(|&x| x) //~ ERROR + .count(); //~ ERROR ``` */ mod map {} @@ -31,13 +29,11 @@ struct NoSend(*const ()); unsafe impl Sync for NoSend {} -fn main() { - let x = Some(NoSend(null())); +let x = Some(NoSend(null())); - x.par_iter() - .filter_map(|&x| Some(x)) //~ ERROR - .count(); //~ ERROR -} +x.par_iter() + .filter_map(|&x| Some(x)) //~ ERROR + .count(); //~ ERROR ``` */ mod filter_map {} @@ -52,13 +48,11 @@ struct NoSend(*const ()); unsafe impl Sync for NoSend {} -fn main() { - let x = Some(NoSend(null())); +let x = Some(NoSend(null())); - x.par_iter() - .cloned() //~ ERROR - .count(); //~ ERROR -} +x.par_iter() + .cloned() //~ ERROR + .count(); //~ ERROR ``` */ mod cloned {} diff --git a/vendor/rayon/src/compile_fail/rc_par_iter.rs b/vendor/rayon/src/compile_fail/rc_par_iter.rs index feaedb38f..aca63e7ac 100644 --- a/vendor/rayon/src/compile_fail/rc_par_iter.rs +++ b/vendor/rayon/src/compile_fail/rc_par_iter.rs @@ -6,12 +6,10 @@ use rayon::prelude::*; use std::rc::Rc; -fn main() { - let x = vec![Rc::new(22), Rc::new(23)]; - let mut y = vec![]; - x.into_par_iter() //~ ERROR no method named `into_par_iter` - .map(|rc| *rc) - .collect_into_vec(&mut y); -} +let x = vec![Rc::new(22), Rc::new(23)]; +let mut y = vec![]; +x.into_par_iter() //~ ERROR no method named `into_par_iter` + .map(|rc| *rc) + .collect_into_vec(&mut y); ``` */ diff --git a/vendor/rayon/src/iter/chunks.rs b/vendor/rayon/src/iter/chunks.rs index be5f84cc7..ec48278d0 100644 --- a/vendor/rayon/src/iter/chunks.rs +++ b/vendor/rayon/src/iter/chunks.rs @@ -90,38 +90,46 @@ where where P: Producer<Item = T>, { - self.callback.callback(ChunkProducer { - chunk_size: self.size, - len: self.len, - base, - }) + let producer = ChunkProducer::new(self.size, self.len, base, Vec::from_iter); + self.callback.callback(producer) } } } } -struct ChunkProducer<P> -where - P: Producer, -{ +pub(super) struct ChunkProducer<P, F> { chunk_size: usize, len: usize, base: P, + map: F, } -impl<P> Producer for ChunkProducer<P> +impl<P, F> ChunkProducer<P, F> { + pub(super) fn new(chunk_size: usize, len: usize, base: P, map: F) -> Self { + Self { + chunk_size, + len, + base, + map, + } + } +} + +impl<P, F, T> Producer for ChunkProducer<P, F> where P: Producer, + F: Fn(P::IntoIter) -> T + Send + Clone, { - type Item = Vec<P::Item>; - type IntoIter = ChunkSeq<P>; + type Item = T; + type IntoIter = std::iter::Map<ChunkSeq<P>, F>; fn into_iter(self) -> Self::IntoIter { - ChunkSeq { + let chunks = ChunkSeq { chunk_size: self.chunk_size, len: self.len, inner: if self.len > 0 { Some(self.base) } else { None }, - } + }; + chunks.map(self.map) } fn split_at(self, index: usize) -> (Self, Self) { @@ -132,11 +140,13 @@ where chunk_size: self.chunk_size, len: elem_index, base: left, + map: self.map.clone(), }, ChunkProducer { chunk_size: self.chunk_size, len: self.len - elem_index, base: right, + map: self.map, }, ) } @@ -150,7 +160,7 @@ where } } -struct ChunkSeq<P> { +pub(super) struct ChunkSeq<P> { chunk_size: usize, len: usize, inner: Option<P>, @@ -160,7 +170,7 @@ impl<P> Iterator for ChunkSeq<P> where P: Producer, { - type Item = Vec<P::Item>; + type Item = P::IntoIter; fn next(&mut self) -> Option<Self::Item> { let producer = self.inner.take()?; @@ -168,11 +178,11 @@ where let (left, right) = producer.split_at(self.chunk_size); self.inner = Some(right); self.len -= self.chunk_size; - Some(left.into_iter().collect()) + Some(left.into_iter()) } else { debug_assert!(self.len > 0); self.len = 0; - Some(producer.into_iter().collect()) + Some(producer.into_iter()) } } @@ -206,11 +216,11 @@ where let (left, right) = producer.split_at(self.len - size); self.inner = Some(left); self.len -= size; - Some(right.into_iter().collect()) + Some(right.into_iter()) } else { debug_assert!(self.len > 0); self.len = 0; - Some(producer.into_iter().collect()) + Some(producer.into_iter()) } } } diff --git a/vendor/rayon/src/iter/filter.rs b/vendor/rayon/src/iter/filter.rs index 38627f7c0..e1b74ba52 100644 --- a/vendor/rayon/src/iter/filter.rs +++ b/vendor/rayon/src/iter/filter.rs @@ -97,7 +97,7 @@ where P: Fn(&T) -> bool + Sync, { fn split_off_left(&self) -> Self { - FilterConsumer::new(self.base.split_off_left(), &self.filter_op) + FilterConsumer::new(self.base.split_off_left(), self.filter_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/filter_map.rs b/vendor/rayon/src/iter/filter_map.rs index f19c38563..db1c7e3f0 100644 --- a/vendor/rayon/src/iter/filter_map.rs +++ b/vendor/rayon/src/iter/filter_map.rs @@ -98,7 +98,7 @@ where P: Fn(T) -> Option<U> + Sync + 'p, { fn split_off_left(&self) -> Self { - FilterMapConsumer::new(self.base.split_off_left(), &self.filter_op) + FilterMapConsumer::new(self.base.split_off_left(), self.filter_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/find.rs b/vendor/rayon/src/iter/find.rs index 971db2b3c..b16ee8446 100644 --- a/vendor/rayon/src/iter/find.rs +++ b/vendor/rayon/src/iter/find.rs @@ -94,7 +94,7 @@ where self.item = iter .into_iter() // stop iterating if another thread has found something - .take_while(not_full(&self.found)) + .take_while(not_full(self.found)) .find(self.find_op); if self.item.is_some() { self.found.store(true, Ordering::Relaxed) diff --git a/vendor/rayon/src/iter/fold_chunks.rs b/vendor/rayon/src/iter/fold_chunks.rs new file mode 100644 index 000000000..185fb1a65 --- /dev/null +++ b/vendor/rayon/src/iter/fold_chunks.rs @@ -0,0 +1,236 @@ +use std::fmt::{self, Debug}; + +use super::chunks::ChunkProducer; +use super::plumbing::*; +use super::*; +use crate::math::div_round_up; + +/// `FoldChunks` is an iterator that groups elements of an underlying iterator and applies a +/// function over them, producing a single value for each group. +/// +/// This struct is created by the [`fold_chunks()`] method on [`IndexedParallelIterator`] +/// +/// [`fold_chunks()`]: trait.IndexedParallelIterator.html#method.fold_chunks +/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] +pub struct FoldChunks<I, ID, F> +where + I: IndexedParallelIterator, +{ + base: I, + chunk_size: usize, + fold_op: F, + identity: ID, +} + +impl<I: IndexedParallelIterator + Debug, ID, F> Debug for FoldChunks<I, ID, F> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Fold") + .field("base", &self.base) + .field("chunk_size", &self.chunk_size) + .finish() + } +} + +impl<I, ID, U, F> FoldChunks<I, ID, F> +where + I: IndexedParallelIterator, + ID: Fn() -> U + Send + Sync, + F: Fn(U, I::Item) -> U + Send + Sync, + U: Send, +{ + /// Creates a new `FoldChunks` iterator + pub(super) fn new(base: I, chunk_size: usize, identity: ID, fold_op: F) -> Self { + FoldChunks { + base, + chunk_size, + identity, + fold_op, + } + } +} + +impl<I, ID, U, F> ParallelIterator for FoldChunks<I, ID, F> +where + I: IndexedParallelIterator, + ID: Fn() -> U + Send + Sync, + F: Fn(U, I::Item) -> U + Send + Sync, + U: Send, +{ + type Item = U; + + fn drive_unindexed<C>(self, consumer: C) -> C::Result + where + C: Consumer<U>, + { + bridge(self, consumer) + } + + fn opt_len(&self) -> Option<usize> { + Some(self.len()) + } +} + +impl<I, ID, U, F> IndexedParallelIterator for FoldChunks<I, ID, F> +where + I: IndexedParallelIterator, + ID: Fn() -> U + Send + Sync, + F: Fn(U, I::Item) -> U + Send + Sync, + U: Send, +{ + fn len(&self) -> usize { + div_round_up(self.base.len(), self.chunk_size) + } + + fn drive<C>(self, consumer: C) -> C::Result + where + C: Consumer<Self::Item>, + { + bridge(self, consumer) + } + + fn with_producer<CB>(self, callback: CB) -> CB::Output + where + CB: ProducerCallback<Self::Item>, + { + let len = self.base.len(); + return self.base.with_producer(Callback { + chunk_size: self.chunk_size, + len, + identity: self.identity, + fold_op: self.fold_op, + callback, + }); + + struct Callback<CB, ID, F> { + chunk_size: usize, + len: usize, + identity: ID, + fold_op: F, + callback: CB, + } + + impl<T, CB, ID, U, F> ProducerCallback<T> for Callback<CB, ID, F> + where + CB: ProducerCallback<U>, + ID: Fn() -> U + Send + Sync, + F: Fn(U, T) -> U + Send + Sync, + { + type Output = CB::Output; + + fn callback<P>(self, base: P) -> CB::Output + where + P: Producer<Item = T>, + { + let identity = &self.identity; + let fold_op = &self.fold_op; + let fold_iter = move |iter: P::IntoIter| iter.fold(identity(), fold_op); + let producer = ChunkProducer::new(self.chunk_size, self.len, base, fold_iter); + self.callback.callback(producer) + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::ops::Add; + + #[test] + fn check_fold_chunks() { + let words = "bishbashbosh!" + .chars() + .collect::<Vec<_>>() + .into_par_iter() + .fold_chunks(4, String::new, |mut s, c| { + s.push(c); + s + }) + .collect::<Vec<_>>(); + + assert_eq!(words, vec!["bish", "bash", "bosh", "!"]); + } + + // 'closure' values for tests below + fn id() -> i32 { + 0 + } + fn sum<T, U>(x: T, y: U) -> T + where + T: Add<U, Output = T>, + { + x + y + } + + #[test] + #[should_panic(expected = "chunk_size must not be zero")] + fn check_fold_chunks_zero_size() { + let _: Vec<i32> = vec![1, 2, 3] + .into_par_iter() + .fold_chunks(0, id, sum) + .collect(); + } + + #[test] + fn check_fold_chunks_even_size() { + assert_eq!( + vec![1 + 2 + 3, 4 + 5 + 6, 7 + 8 + 9], + (1..10) + .into_par_iter() + .fold_chunks(3, id, sum) + .collect::<Vec<i32>>() + ); + } + + #[test] + fn check_fold_chunks_empty() { + let v: Vec<i32> = vec![]; + let expected: Vec<i32> = vec![]; + assert_eq!( + expected, + v.into_par_iter() + .fold_chunks(2, id, sum) + .collect::<Vec<i32>>() + ); + } + + #[test] + fn check_fold_chunks_len() { + assert_eq!(4, (0..8).into_par_iter().fold_chunks(2, id, sum).len()); + assert_eq!(3, (0..9).into_par_iter().fold_chunks(3, id, sum).len()); + assert_eq!(3, (0..8).into_par_iter().fold_chunks(3, id, sum).len()); + assert_eq!(1, (&[1]).par_iter().fold_chunks(3, id, sum).len()); + assert_eq!(0, (0..0).into_par_iter().fold_chunks(3, id, sum).len()); + } + + #[test] + fn check_fold_chunks_uneven() { + let cases: Vec<(Vec<u32>, usize, Vec<u32>)> = vec![ + ((0..5).collect(), 3, vec![0 + 1 + 2, 3 + 4]), + (vec![1], 5, vec![1]), + ((0..4).collect(), 3, vec![0 + 1 + 2, 3]), + ]; + + for (i, (v, n, expected)) in cases.into_iter().enumerate() { + let mut res: Vec<u32> = vec![]; + v.par_iter() + .fold_chunks(n, || 0, sum) + .collect_into_vec(&mut res); + assert_eq!(expected, res, "Case {} failed", i); + + res.truncate(0); + v.into_par_iter() + .fold_chunks(n, || 0, sum) + .rev() + .collect_into_vec(&mut res); + assert_eq!( + expected.into_iter().rev().collect::<Vec<u32>>(), + res, + "Case {} reversed failed", + i + ); + } + } +} diff --git a/vendor/rayon/src/iter/fold_chunks_with.rs b/vendor/rayon/src/iter/fold_chunks_with.rs new file mode 100644 index 000000000..af120aec4 --- /dev/null +++ b/vendor/rayon/src/iter/fold_chunks_with.rs @@ -0,0 +1,231 @@ +use std::fmt::{self, Debug}; + +use super::chunks::ChunkProducer; +use super::plumbing::*; +use super::*; +use crate::math::div_round_up; + +/// `FoldChunksWith` is an iterator that groups elements of an underlying iterator and applies a +/// function over them, producing a single value for each group. +/// +/// This struct is created by the [`fold_chunks_with()`] method on [`IndexedParallelIterator`] +/// +/// [`fold_chunks_with()`]: trait.IndexedParallelIterator.html#method.fold_chunks +/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] +pub struct FoldChunksWith<I, U, F> +where + I: IndexedParallelIterator, +{ + base: I, + chunk_size: usize, + item: U, + fold_op: F, +} + +impl<I: IndexedParallelIterator + Debug, U: Debug, F> Debug for FoldChunksWith<I, U, F> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Fold") + .field("base", &self.base) + .field("chunk_size", &self.chunk_size) + .field("item", &self.item) + .finish() + } +} + +impl<I, U, F> FoldChunksWith<I, U, F> +where + I: IndexedParallelIterator, + U: Send + Clone, + F: Fn(U, I::Item) -> U + Send + Sync, +{ + /// Creates a new `FoldChunksWith` iterator + pub(super) fn new(base: I, chunk_size: usize, item: U, fold_op: F) -> Self { + FoldChunksWith { + base, + chunk_size, + item, + fold_op, + } + } +} + +impl<I, U, F> ParallelIterator for FoldChunksWith<I, U, F> +where + I: IndexedParallelIterator, + U: Send + Clone, + F: Fn(U, I::Item) -> U + Send + Sync, +{ + type Item = U; + + fn drive_unindexed<C>(self, consumer: C) -> C::Result + where + C: Consumer<U>, + { + bridge(self, consumer) + } + + fn opt_len(&self) -> Option<usize> { + Some(self.len()) + } +} + +impl<I, U, F> IndexedParallelIterator for FoldChunksWith<I, U, F> +where + I: IndexedParallelIterator, + U: Send + Clone, + F: Fn(U, I::Item) -> U + Send + Sync, +{ + fn len(&self) -> usize { + div_round_up(self.base.len(), self.chunk_size) + } + + fn drive<C>(self, consumer: C) -> C::Result + where + C: Consumer<Self::Item>, + { + bridge(self, consumer) + } + + fn with_producer<CB>(self, callback: CB) -> CB::Output + where + CB: ProducerCallback<Self::Item>, + { + let len = self.base.len(); + return self.base.with_producer(Callback { + chunk_size: self.chunk_size, + len, + item: self.item, + fold_op: self.fold_op, + callback, + }); + + struct Callback<CB, T, F> { + chunk_size: usize, + len: usize, + item: T, + fold_op: F, + callback: CB, + } + + impl<T, U, F, CB> ProducerCallback<T> for Callback<CB, U, F> + where + CB: ProducerCallback<U>, + U: Send + Clone, + F: Fn(U, T) -> U + Send + Sync, + { + type Output = CB::Output; + + fn callback<P>(self, base: P) -> CB::Output + where + P: Producer<Item = T>, + { + let item = self.item; + let fold_op = &self.fold_op; + let fold_iter = move |iter: P::IntoIter| iter.fold(item.clone(), fold_op); + let producer = ChunkProducer::new(self.chunk_size, self.len, base, fold_iter); + self.callback.callback(producer) + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::ops::Add; + + #[test] + fn check_fold_chunks_with() { + let words = "bishbashbosh!" + .chars() + .collect::<Vec<_>>() + .into_par_iter() + .fold_chunks_with(4, String::new(), |mut s, c| { + s.push(c); + s + }) + .collect::<Vec<_>>(); + + assert_eq!(words, vec!["bish", "bash", "bosh", "!"]); + } + + // 'closure' value for tests below + fn sum<T, U>(x: T, y: U) -> T + where + T: Add<U, Output = T>, + { + x + y + } + + #[test] + #[should_panic(expected = "chunk_size must not be zero")] + fn check_fold_chunks_zero_size() { + let _: Vec<i32> = vec![1, 2, 3] + .into_par_iter() + .fold_chunks_with(0, 0, sum) + .collect(); + } + + #[test] + fn check_fold_chunks_even_size() { + assert_eq!( + vec![1 + 2 + 3, 4 + 5 + 6, 7 + 8 + 9], + (1..10) + .into_par_iter() + .fold_chunks_with(3, 0, sum) + .collect::<Vec<i32>>() + ); + } + + #[test] + fn check_fold_chunks_with_empty() { + let v: Vec<i32> = vec![]; + let expected: Vec<i32> = vec![]; + assert_eq!( + expected, + v.into_par_iter() + .fold_chunks_with(2, 0, sum) + .collect::<Vec<i32>>() + ); + } + + #[test] + fn check_fold_chunks_len() { + assert_eq!(4, (0..8).into_par_iter().fold_chunks_with(2, 0, sum).len()); + assert_eq!(3, (0..9).into_par_iter().fold_chunks_with(3, 0, sum).len()); + assert_eq!(3, (0..8).into_par_iter().fold_chunks_with(3, 0, sum).len()); + assert_eq!(1, (&[1]).par_iter().fold_chunks_with(3, 0, sum).len()); + assert_eq!(0, (0..0).into_par_iter().fold_chunks_with(3, 0, sum).len()); + } + + #[test] + fn check_fold_chunks_uneven() { + let cases: Vec<(Vec<u32>, usize, Vec<u32>)> = vec![ + ((0..5).collect(), 3, vec![0 + 1 + 2, 3 + 4]), + (vec![1], 5, vec![1]), + ((0..4).collect(), 3, vec![0 + 1 + 2, 3]), + ]; + + for (i, (v, n, expected)) in cases.into_iter().enumerate() { + let mut res: Vec<u32> = vec![]; + v.par_iter() + .fold_chunks_with(n, 0, sum) + .collect_into_vec(&mut res); + assert_eq!(expected, res, "Case {} failed", i); + + res.truncate(0); + v.into_par_iter() + .fold_chunks_with(n, 0, sum) + .rev() + .collect_into_vec(&mut res); + assert_eq!( + expected.into_iter().rev().collect::<Vec<u32>>(), + res, + "Case {} reversed failed", + i + ); + } + } +} diff --git a/vendor/rayon/src/iter/inspect.rs b/vendor/rayon/src/iter/inspect.rs index 9b1cd094d..c50ca022d 100644 --- a/vendor/rayon/src/iter/inspect.rs +++ b/vendor/rayon/src/iter/inspect.rs @@ -209,7 +209,7 @@ where F: Fn(&T) + Sync, { fn split_off_left(&self) -> Self { - InspectConsumer::new(self.base.split_off_left(), &self.inspect_op) + InspectConsumer::new(self.base.split_off_left(), self.inspect_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/interleave.rs b/vendor/rayon/src/iter/interleave.rs index b5d43d53d..3cacc49f9 100644 --- a/vendor/rayon/src/iter/interleave.rs +++ b/vendor/rayon/src/iter/interleave.rs @@ -310,16 +310,16 @@ where { #[inline] fn next_back(&mut self) -> Option<I::Item> { - if self.i.len() == self.j.len() { - if self.i_next { - self.i.next_back() - } else { - self.j.next_back() + match self.i.len().cmp(&self.j.len()) { + Ordering::Less => self.j.next_back(), + Ordering::Equal => { + if self.i_next { + self.i.next_back() + } else { + self.j.next_back() + } } - } else if self.i.len() < self.j.len() { - self.j.next_back() - } else { - self.i.next_back() + Ordering::Greater => self.i.next_back(), } } } diff --git a/vendor/rayon/src/iter/map.rs b/vendor/rayon/src/iter/map.rs index f2a35ff8c..da14d4082 100644 --- a/vendor/rayon/src/iter/map.rs +++ b/vendor/rayon/src/iter/map.rs @@ -213,7 +213,7 @@ where R: Send, { fn split_off_left(&self) -> Self { - MapConsumer::new(self.base.split_off_left(), &self.map_op) + MapConsumer::new(self.base.split_off_left(), self.map_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/iter/mod.rs b/vendor/rayon/src/iter/mod.rs index 89e96fcef..98c93267f 100644 --- a/vendor/rayon/src/iter/mod.rs +++ b/vendor/rayon/src/iter/mod.rs @@ -119,6 +119,8 @@ mod flat_map_iter; mod flatten; mod flatten_iter; mod fold; +mod fold_chunks; +mod fold_chunks_with; mod for_each; mod from_par_iter; mod inspect; @@ -140,6 +142,7 @@ mod repeat; mod rev; mod skip; mod splitter; +mod step_by; mod sum; mod take; mod try_fold; @@ -165,6 +168,8 @@ pub use self::{ flatten::Flatten, flatten_iter::FlattenIter, fold::{Fold, FoldWith}, + fold_chunks::FoldChunks, + fold_chunks_with::FoldChunksWith, inspect::Inspect, interleave::Interleave, interleave_shortest::InterleaveShortest, @@ -181,6 +186,7 @@ pub use self::{ rev::Rev, skip::Skip, splitter::{split, Split}, + step_by::StepBy, take::Take, try_fold::{TryFold, TryFoldWith}, update::Update, @@ -189,10 +195,6 @@ pub use self::{ zip_eq::ZipEq, }; -mod step_by; -#[cfg(has_step_by_rev)] -pub use self::step_by::StepBy; - /// `IntoParallelIterator` implements the conversion to a [`ParallelIterator`]. /// /// By implementing `IntoParallelIterator` for a type, you define how it will @@ -1124,7 +1126,7 @@ pub trait ParallelIterator: Sized + Send { /// multiple sums. The number of results is nondeterministic, as /// is the point where the breaks occur. /// - /// So if did the same parallel fold (`fold(0, |a,b| a+b)`) on + /// So if we did the same parallel fold (`fold(0, |a,b| a+b)`) on /// our example list, we might wind up with a sequence of two numbers, /// like so: /// @@ -2241,6 +2243,8 @@ impl<T: ParallelIterator> IntoParallelIterator for T { /// those points. /// /// **Note:** Not implemented for `u64`, `i64`, `u128`, or `i128` ranges +// Waiting for `ExactSizeIterator::is_empty` to be stabilized. See rust-lang/rust#35428 +#[allow(clippy::len_without_is_empty)] pub trait IndexedParallelIterator: ParallelIterator { /// Collects the results of the iterator into the specified /// vector. The vector is always truncated before execution @@ -2339,13 +2343,18 @@ pub trait IndexedParallelIterator: ParallelIterator { /// // we should never get here /// assert_eq!(1, zipped.len()); /// ``` + #[track_caller] fn zip_eq<Z>(self, zip_op: Z) -> ZipEq<Self, Z::Iter> where Z: IntoParallelIterator, Z::Iter: IndexedParallelIterator, { let zip_op_iter = zip_op.into_par_iter(); - assert_eq!(self.len(), zip_op_iter.len()); + assert_eq!( + self.len(), + zip_op_iter.len(), + "iterators must have the same length" + ); ZipEq::new(self, zip_op_iter) } @@ -2415,6 +2424,89 @@ pub trait IndexedParallelIterator: ParallelIterator { Chunks::new(self, chunk_size) } + /// Splits an iterator into fixed-size chunks, performing a sequential [`fold()`] on + /// each chunk. + /// + /// Returns an iterator that produces a folded result for each chunk of items + /// produced by this iterator. + /// + /// This works essentially like: + /// + /// ```text + /// iter.chunks(chunk_size) + /// .map(|chunk| + /// chunk.into_iter() + /// .fold(identity, fold_op) + /// ) + /// ``` + /// + /// except there is no per-chunk allocation overhead. + /// + /// [`fold()`]: std::iter::Iterator#method.fold + /// + /// **Panics** if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// let nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + /// let chunk_sums = nums.into_par_iter().fold_chunks(2, || 0, |a, n| a + n).collect::<Vec<_>>(); + /// assert_eq!(chunk_sums, vec![3, 7, 11, 15, 19]); + /// ``` + #[track_caller] + fn fold_chunks<T, ID, F>( + self, + chunk_size: usize, + identity: ID, + fold_op: F, + ) -> FoldChunks<Self, ID, F> + where + ID: Fn() -> T + Send + Sync, + F: Fn(T, Self::Item) -> T + Send + Sync, + T: Send, + { + assert!(chunk_size != 0, "chunk_size must not be zero"); + FoldChunks::new(self, chunk_size, identity, fold_op) + } + + /// Splits an iterator into fixed-size chunks, performing a sequential [`fold()`] on + /// each chunk. + /// + /// Returns an iterator that produces a folded result for each chunk of items + /// produced by this iterator. + /// + /// This works essentially like `fold_chunks(chunk_size, || init.clone(), fold_op)`, + /// except it doesn't require the `init` type to be `Sync`, nor any other form of + /// added synchronization. + /// + /// [`fold()`]: std::iter::Iterator#method.fold + /// + /// **Panics** if `chunk_size` is 0. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// let nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + /// let chunk_sums = nums.into_par_iter().fold_chunks_with(2, 0, |a, n| a + n).collect::<Vec<_>>(); + /// assert_eq!(chunk_sums, vec![3, 7, 11, 15, 19]); + /// ``` + #[track_caller] + fn fold_chunks_with<T, F>( + self, + chunk_size: usize, + init: T, + fold_op: F, + ) -> FoldChunksWith<Self, T, F> + where + T: Send + Clone, + F: Fn(T, Self::Item) -> T + Send + Sync, + { + assert!(chunk_size != 0, "chunk_size must not be zero"); + FoldChunksWith::new(self, chunk_size, init, fold_op) + } + /// Lexicographically compares the elements of this `ParallelIterator` with those of /// another. /// @@ -2601,11 +2693,6 @@ pub trait IndexedParallelIterator: ParallelIterator { /// /// assert_eq!(result, [3, 6, 9]) /// ``` - /// - /// # Compatibility - /// - /// This method is only available on Rust 1.38 or greater. - #[cfg(has_step_by_rev)] fn step_by(self, step: usize) -> StepBy<Self> { StepBy::new(self, step) } @@ -3146,20 +3233,9 @@ pub trait ParallelDrainRange<Idx = usize> { /// stable clone of the standard library's `Try` trait, as yet unstable. mod private { use std::convert::Infallible; + use std::ops::ControlFlow::{self, Break, Continue}; use std::task::Poll; - #[cfg(has_control_flow)] - pub(crate) use std::ops::ControlFlow; - - #[cfg(not(has_control_flow))] - #[allow(missing_debug_implementations)] - pub enum ControlFlow<B, C = ()> { - Continue(C), - Break(B), - } - - use self::ControlFlow::{Break, Continue}; - /// Clone of `std::ops::Try`. /// /// Implementing this trait is not permitted outside of `rayon`. @@ -3176,7 +3252,6 @@ mod private { fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; } - #[cfg(has_control_flow)] impl<B, C> Try for ControlFlow<B, C> { private_impl! {} diff --git a/vendor/rayon/src/iter/plumbing/README.md b/vendor/rayon/src/iter/plumbing/README.md index cd94eae30..dbee36ba0 100644 --- a/vendor/rayon/src/iter/plumbing/README.md +++ b/vendor/rayon/src/iter/plumbing/README.md @@ -124,7 +124,7 @@ implement `IndexedParallelIterator`. The `bridge` function will then connect the consumer, which is handling the `flat_map` and `for_each`, with the producer, which is -handling the `zip` and its preecessors. It will split down until the +handling the `zip` and its predecessors. It will split down until the chunks seem reasonably small, then pull items from the producer and feed them to the consumer. diff --git a/vendor/rayon/src/iter/step_by.rs b/vendor/rayon/src/iter/step_by.rs index 863de3cf0..94b8334e8 100644 --- a/vendor/rayon/src/iter/step_by.rs +++ b/vendor/rayon/src/iter/step_by.rs @@ -1,4 +1,3 @@ -#![cfg(has_step_by_rev)] use std::cmp::min; use super::plumbing::*; diff --git a/vendor/rayon/src/iter/test.rs b/vendor/rayon/src/iter/test.rs index bc5106bec..94323d79d 100644 --- a/vendor/rayon/src/iter/test.rs +++ b/vendor/rayon/src/iter/test.rs @@ -117,13 +117,10 @@ fn fold_map_reduce() { let r1 = (0_i32..32) .into_par_iter() .with_max_len(1) - .fold( - || vec![], - |mut v, e| { - v.push(e); - v - }, - ) + .fold(Vec::new, |mut v, e| { + v.push(e); + v + }) .map(|v| vec![v]) .reduce_with(|mut v_a, v_b| { v_a.extend(v_b); @@ -394,7 +391,7 @@ fn check_slice_mut_indexed() { #[test] fn check_vec_indexed() { let a = vec![1, 2, 3]; - is_indexed(a.clone().into_par_iter()); + is_indexed(a.into_par_iter()); } #[test] @@ -1371,10 +1368,10 @@ fn check_find_is_present() { let counter = AtomicUsize::new(0); let value: Option<i32> = (0_i32..2048).into_par_iter().find_any(|&p| { counter.fetch_add(1, Ordering::SeqCst); - p >= 1024 && p < 1096 + (1024..1096).contains(&p) }); let q = value.unwrap(); - assert!(q >= 1024 && q < 1096); + assert!((1024..1096).contains(&q)); assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one } @@ -1892,7 +1889,7 @@ fn check_either() { // try an indexed iterator let left: E = Either::Left(v.clone().into_par_iter()); - assert!(left.enumerate().eq(v.clone().into_par_iter().enumerate())); + assert!(left.enumerate().eq(v.into_par_iter().enumerate())); } #[test] @@ -2063,7 +2060,7 @@ fn check_chunks_len() { assert_eq!(4, (0..8).into_par_iter().chunks(2).len()); assert_eq!(3, (0..9).into_par_iter().chunks(3).len()); assert_eq!(3, (0..8).into_par_iter().chunks(3).len()); - assert_eq!(1, (&[1]).par_iter().chunks(3).len()); + assert_eq!(1, [1].par_iter().chunks(3).len()); assert_eq!(0, (0..0).into_par_iter().chunks(3).len()); } diff --git a/vendor/rayon/src/iter/try_fold.rs b/vendor/rayon/src/iter/try_fold.rs index c1881d10f..6d1048d75 100644 --- a/vendor/rayon/src/iter/try_fold.rs +++ b/vendor/rayon/src/iter/try_fold.rs @@ -2,10 +2,9 @@ use super::plumbing::*; use super::ParallelIterator; use super::Try; -use super::private::ControlFlow::{self, Break, Continue}; - use std::fmt::{self, Debug}; use std::marker::PhantomData; +use std::ops::ControlFlow::{self, Break, Continue}; impl<U, I, ID, F> TryFold<I, U, ID, F> where diff --git a/vendor/rayon/src/iter/try_reduce.rs b/vendor/rayon/src/iter/try_reduce.rs index 7bf6cc4a5..35a724c94 100644 --- a/vendor/rayon/src/iter/try_reduce.rs +++ b/vendor/rayon/src/iter/try_reduce.rs @@ -2,8 +2,7 @@ use super::plumbing::*; use super::ParallelIterator; use super::Try; -use super::private::ControlFlow::{self, Break, Continue}; - +use std::ops::ControlFlow::{self, Break, Continue}; use std::sync::atomic::{AtomicBool, Ordering}; pub(super) fn try_reduce<PI, R, ID, T>(pi: PI, identity: ID, reduce_op: R) -> T diff --git a/vendor/rayon/src/iter/try_reduce_with.rs b/vendor/rayon/src/iter/try_reduce_with.rs index 9fe34d61d..cd7c83e27 100644 --- a/vendor/rayon/src/iter/try_reduce_with.rs +++ b/vendor/rayon/src/iter/try_reduce_with.rs @@ -2,8 +2,7 @@ use super::plumbing::*; use super::ParallelIterator; use super::Try; -use super::private::ControlFlow::{self, Break, Continue}; - +use std::ops::ControlFlow::{self, Break, Continue}; use std::sync::atomic::{AtomicBool, Ordering}; pub(super) fn try_reduce_with<PI, R, T>(pi: PI, reduce_op: R) -> Option<T> diff --git a/vendor/rayon/src/iter/update.rs b/vendor/rayon/src/iter/update.rs index 373a4d772..c693ac8d6 100644 --- a/vendor/rayon/src/iter/update.rs +++ b/vendor/rayon/src/iter/update.rs @@ -210,7 +210,7 @@ where F: Fn(&mut T) + Send + Sync, { fn split_off_left(&self) -> Self { - UpdateConsumer::new(self.base.split_off_left(), &self.update_op) + UpdateConsumer::new(self.base.split_off_left(), self.update_op) } fn to_reducer(&self) -> Self::Reducer { diff --git a/vendor/rayon/src/lib.rs b/vendor/rayon/src/lib.rs index b59f3fa2b..25a5e16a7 100644 --- a/vendor/rayon/src/lib.rs +++ b/vendor/rayon/src/lib.rs @@ -1,4 +1,3 @@ -#![doc(html_root_url = "https://docs.rs/rayon/1.5")] #![deny(missing_debug_implementations)] #![deny(missing_docs)] #![deny(unreachable_pub)] @@ -114,6 +113,7 @@ pub use rayon_core::ThreadBuilder; pub use rayon_core::ThreadPool; pub use rayon_core::ThreadPoolBuildError; pub use rayon_core::ThreadPoolBuilder; +pub use rayon_core::{broadcast, spawn_broadcast, BroadcastContext}; pub use rayon_core::{current_num_threads, current_thread_index, max_num_threads}; pub use rayon_core::{in_place_scope, scope, Scope}; pub use rayon_core::{in_place_scope_fifo, scope_fifo, ScopeFifo}; @@ -136,6 +136,13 @@ unsafe impl<T: Send> Send for SendPtr<T> {} // SAFETY: !Sync for raw pointers is not for safety, just as a lint unsafe impl<T: Send> Sync for SendPtr<T> {} +impl<T> SendPtr<T> { + // Helper to avoid disjoint captures of `send_ptr.0` + fn get(self) -> *mut T { + self.0 + } +} + // Implement Clone without the T: Clone bound from the derive impl<T> Clone for SendPtr<T> { fn clone(&self) -> Self { diff --git a/vendor/rayon/src/math.rs b/vendor/rayon/src/math.rs index 9de588965..3a630be14 100644 --- a/vendor/rayon/src/math.rs +++ b/vendor/rayon/src/math.rs @@ -1,7 +1,7 @@ use std::ops::{Bound, Range, RangeBounds}; /// Divide `n` by `divisor`, and round up to the nearest integer -/// if not evenly divisable. +/// if not evenly divisible. #[inline] pub(super) fn div_round_up(n: usize, divisor: usize) -> usize { debug_assert!(divisor != 0, "Division by zero!"); diff --git a/vendor/rayon/src/slice/chunks.rs b/vendor/rayon/src/slice/chunks.rs index 5b145bdd8..a3cc70953 100644 --- a/vendor/rayon/src/slice/chunks.rs +++ b/vendor/rayon/src/slice/chunks.rs @@ -317,7 +317,7 @@ impl<'data, T: Send> ChunksExactMut<'data, T> { /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. Subsequent calls will return an empty slice. pub fn take_remainder(&mut self) -> &'data mut [T] { - std::mem::replace(&mut self.rem, &mut []) + std::mem::take(&mut self.rem) } } diff --git a/vendor/rayon/src/slice/mergesort.rs b/vendor/rayon/src/slice/mergesort.rs index a24ba65b7..fec309d27 100644 --- a/vendor/rayon/src/slice/mergesort.rs +++ b/vendor/rayon/src/slice/mergesort.rs @@ -205,9 +205,8 @@ where impl<T> Drop for MergeHole<T> { fn drop(&mut self) { // `T` is not a zero-sized type, so it's okay to divide by its size. - let len = (self.end as usize - self.start as usize) / size_of::<T>(); unsafe { - // TODO 1.47: let len = self.end.offset_from(self.start) as usize; + let len = self.end.offset_from(self.start) as usize; ptr::copy_nonoverlapping(self.start, self.dest, len); } } @@ -491,8 +490,8 @@ where let dest_l = SendPtr(dest); let dest_r = SendPtr(dest.add(left_l.len() + right_l.len())); rayon_core::join( - || par_merge(left_l, right_l, dest_l.0, is_less), - || par_merge(left_r, right_r, dest_r.0, is_less), + move || par_merge(left_l, right_l, dest_l.get(), is_less), + move || par_merge(left_r, right_r, dest_r.get(), is_less), ); } // Finally, `s` gets dropped if we used sequential merge, thus copying the remaining elements @@ -570,7 +569,7 @@ unsafe fn recurse<T, F>( // After recursive calls finish we'll have to merge chunks `(start, mid)` and `(mid, end)` from // `src` into `dest`. If the current invocation has to store the result into `buf`, we'll - // merge chunks from `v` into `buf`, and viceversa. + // merge chunks from `v` into `buf`, and vice versa. // // Recursive calls flip `into_buf` at each level of recursion. More concretely, `par_merge` // merges chunks from `buf` into `v` at the first level, from `v` into `buf` at the second @@ -593,8 +592,8 @@ unsafe fn recurse<T, F>( let v = SendPtr(v); let buf = SendPtr(buf); rayon_core::join( - || recurse(v.0, buf.0, left, !into_buf, is_less), - || recurse(v.0, buf.0, right, !into_buf, is_less), + move || recurse(v.get(), buf.get(), left, !into_buf, is_less), + move || recurse(v.get(), buf.get(), right, !into_buf, is_less), ); // Everything went all right - recursive calls didn't panic. @@ -661,16 +660,17 @@ where // Wrap pointer in SendPtr so that it can be sent to another thread // See the documentation of SendPtr for a full explanation let buf = SendPtr(buf); + let is_less = &is_less; v.par_chunks_mut(CHUNK_LENGTH) .with_max_len(1) .enumerate() - .map(|(i, chunk)| { + .map(move |(i, chunk)| { let l = CHUNK_LENGTH * i; let r = l + chunk.len(); unsafe { - let buf = buf.0.add(l); - (l, r, mergesort(chunk, buf, &is_less)) + let buf = buf.get().add(l); + (l, r, mergesort(chunk, buf, is_less)) } }) .collect::<Vec<_>>() @@ -731,7 +731,7 @@ mod tests { check(&[1, 2, 2, 2, 2, 3], &[]); check(&[], &[1, 2, 2, 2, 2, 3]); - let ref mut rng = thread_rng(); + let rng = &mut thread_rng(); for _ in 0..100 { let limit: u32 = rng.gen_range(1..21); diff --git a/vendor/rayon/src/slice/mod.rs b/vendor/rayon/src/slice/mod.rs index a4e777374..dab56deb3 100644 --- a/vendor/rayon/src/slice/mod.rs +++ b/vendor/rayon/src/slice/mod.rs @@ -85,6 +85,7 @@ pub trait ParallelSlice<T: Sync> { /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_chunks(2).collect(); /// assert_eq!(chunks, vec![&[1, 2][..], &[3, 4], &[5]]); /// ``` + #[track_caller] fn par_chunks(&self, chunk_size: usize) -> Chunks<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); Chunks::new(chunk_size, self.as_parallel_slice()) @@ -104,6 +105,7 @@ pub trait ParallelSlice<T: Sync> { /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_chunks_exact(2).collect(); /// assert_eq!(chunks, vec![&[1, 2][..], &[3, 4]]); /// ``` + #[track_caller] fn par_chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); ChunksExact::new(chunk_size, self.as_parallel_slice()) @@ -123,6 +125,7 @@ pub trait ParallelSlice<T: Sync> { /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_rchunks(2).collect(); /// assert_eq!(chunks, vec![&[4, 5][..], &[2, 3], &[1]]); /// ``` + #[track_caller] fn par_rchunks(&self, chunk_size: usize) -> RChunks<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); RChunks::new(chunk_size, self.as_parallel_slice()) @@ -142,6 +145,7 @@ pub trait ParallelSlice<T: Sync> { /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_rchunks_exact(2).collect(); /// assert_eq!(chunks, vec![&[4, 5][..], &[2, 3]]); /// ``` + #[track_caller] fn par_rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); RChunksExact::new(chunk_size, self.as_parallel_slice()) @@ -199,6 +203,7 @@ pub trait ParallelSliceMut<T: Send> { /// .for_each(|slice| slice.reverse()); /// assert_eq!(array, [2, 1, 4, 3, 5]); /// ``` + #[track_caller] fn par_chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); ChunksMut::new(chunk_size, self.as_parallel_slice_mut()) @@ -220,6 +225,7 @@ pub trait ParallelSliceMut<T: Send> { /// .for_each(|slice| slice.reverse()); /// assert_eq!(array, [3, 2, 1, 4, 5]); /// ``` + #[track_caller] fn par_chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); ChunksExactMut::new(chunk_size, self.as_parallel_slice_mut()) @@ -241,6 +247,7 @@ pub trait ParallelSliceMut<T: Send> { /// .for_each(|slice| slice.reverse()); /// assert_eq!(array, [1, 3, 2, 5, 4]); /// ``` + #[track_caller] fn par_rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); RChunksMut::new(chunk_size, self.as_parallel_slice_mut()) @@ -262,6 +269,7 @@ pub trait ParallelSliceMut<T: Send> { /// .for_each(|slice| slice.reverse()); /// assert_eq!(array, [1, 2, 5, 4, 3]); /// ``` + #[track_caller] fn par_rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> { assert!(chunk_size != 0, "chunk_size must not be zero"); RChunksExactMut::new(chunk_size, self.as_parallel_slice_mut()) diff --git a/vendor/rayon/src/slice/quicksort.rs b/vendor/rayon/src/slice/quicksort.rs index 87fb724c3..d71079ec3 100644 --- a/vendor/rayon/src/slice/quicksort.rs +++ b/vendor/rayon/src/slice/quicksort.rs @@ -191,25 +191,25 @@ where // This binary heap respects the invariant `parent >= child`. let sift_down = |v: &mut [T], mut node| { loop { - // Children of `node`: - let left = 2 * node + 1; - let right = 2 * node + 2; + // Children of `node`. + let mut child = 2 * node + 1; + if child >= v.len() { + break; + } // Choose the greater child. - let greater = if right < v.len() && is_less(&v[left], &v[right]) { - right - } else { - left - }; + if child + 1 < v.len() && is_less(&v[child], &v[child + 1]) { + child += 1; + } // Stop if the invariant holds at `node`. - if greater >= v.len() || !is_less(&v[node], &v[greater]) { + if !is_less(&v[node], &v[child]) { break; } // Swap `node` with the greater child, move one step down, and continue sifting. - v.swap(node, greater); - node = greater; + v.swap(node, child); + node = child; } }; @@ -426,7 +426,7 @@ where // safe. Otherwise, the debug assertions in the `is_done` case guarantee that // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account // for the smaller number of remaining elements. - l = unsafe { l.offset(block_l as isize) }; + l = unsafe { l.add(block_l) }; } if start_r == end_r { @@ -629,8 +629,7 @@ fn break_patterns<T>(v: &mut [T]) { random }; let mut gen_usize = || { - // TODO 1.53: if usize::BITS <= 32 { - if mem::size_of::<usize>() <= 4 { + if usize::BITS <= 32 { gen_u32() as usize } else { (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize @@ -676,6 +675,7 @@ where let len = v.len(); // Three indices near which we are going to choose a pivot. + #[allow(clippy::identity_op)] let mut a = len / 4 * 1; let mut b = len / 4 * 2; let mut c = len / 4 * 3; @@ -850,8 +850,7 @@ where } // Limit the number of imbalanced partitions to `floor(log2(len)) + 1`. - // TODO 1.53: let limit = usize::BITS - v.len().leading_zeros(); - let limit = mem::size_of::<usize>() as u32 * 8 - v.len().leading_zeros(); + let limit = usize::BITS - v.len().leading_zeros(); recurse(v, &is_less, None, limit); } @@ -864,7 +863,7 @@ mod tests { #[test] fn test_heapsort() { - let ref mut rng = thread_rng(); + let rng = &mut thread_rng(); for len in (0..25).chain(500..501) { for &modulus in &[5, 10, 100] { @@ -891,8 +890,8 @@ mod tests { heapsort(&mut v, &|_, _| thread_rng().gen()); heapsort(&mut v, &|a, b| a < b); - for i in 0..v.len() { - assert_eq!(v[i], i); + for (i, &entry) in v.iter().enumerate() { + assert_eq!(entry, i); } } } diff --git a/vendor/rayon/src/slice/rchunks.rs b/vendor/rayon/src/slice/rchunks.rs index 4ff712548..63e765d77 100644 --- a/vendor/rayon/src/slice/rchunks.rs +++ b/vendor/rayon/src/slice/rchunks.rs @@ -314,7 +314,7 @@ impl<'data, T: Send> RChunksExactMut<'data, T> { /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. Subsequent calls will return an empty slice. pub fn take_remainder(&mut self) -> &'data mut [T] { - std::mem::replace(&mut self.rem, &mut []) + std::mem::take(&mut self.rem) } } diff --git a/vendor/rayon/src/slice/test.rs b/vendor/rayon/src/slice/test.rs index 4325aa88d..f74ca0f74 100644 --- a/vendor/rayon/src/slice/test.rs +++ b/vendor/rayon/src/slice/test.rs @@ -10,7 +10,7 @@ macro_rules! sort { ($f:ident, $name:ident) => { #[test] fn $name() { - let ref mut rng = thread_rng(); + let rng = &mut thread_rng(); for len in (0..25).chain(500..501) { for &modulus in &[5, 10, 100] { diff --git a/vendor/rayon/src/str.rs b/vendor/rayon/src/str.rs index 7afda3063..c85754e3d 100644 --- a/vendor/rayon/src/str.rs +++ b/vendor/rayon/src/str.rs @@ -689,11 +689,7 @@ pub struct Lines<'ch>(&'ch str); #[inline] fn no_carriage_return(line: &str) -> &str { - if line.ends_with('\r') { - &line[..line.len() - 1] - } else { - line - } + line.strip_suffix('\r').unwrap_or(line) } impl<'ch> ParallelIterator for Lines<'ch> { diff --git a/vendor/rayon/src/vec.rs b/vendor/rayon/src/vec.rs index e07963922..c804b0f33 100644 --- a/vendor/rayon/src/vec.rs +++ b/vendor/rayon/src/vec.rs @@ -132,7 +132,7 @@ impl<'data, T: Send> IndexedParallelIterator for Drain<'data, T> { self.range.len() } - fn with_producer<CB>(mut self, callback: CB) -> CB::Output + fn with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>, { @@ -141,7 +141,7 @@ impl<'data, T: Send> IndexedParallelIterator for Drain<'data, T> { self.vec.set_len(self.range.start); // Create the producer as the exclusive "owner" of the slice. - let producer = DrainProducer::from_vec(&mut self.vec, self.range.len()); + let producer = DrainProducer::from_vec(self.vec, self.range.len()); // The producer will move or drop each item from the drained range. callback.callback(producer) @@ -151,22 +151,24 @@ impl<'data, T: Send> IndexedParallelIterator for Drain<'data, T> { impl<'data, T: Send> Drop for Drain<'data, T> { fn drop(&mut self) { - if self.range.len() > 0 { - let Range { start, end } = self.range; - if self.vec.len() != start { - // We must not have produced, so just call a normal drain to remove the items. - assert_eq!(self.vec.len(), self.orig_len); - self.vec.drain(start..end); - } else if end < self.orig_len { - // The producer was responsible for consuming the drained items. - // Move the tail items to their new place, then set the length to include them. - unsafe { - let ptr = self.vec.as_mut_ptr().add(start); - let tail_ptr = self.vec.as_ptr().add(end); - let tail_len = self.orig_len - end; - ptr::copy(tail_ptr, ptr, tail_len); - self.vec.set_len(start + tail_len); - } + let Range { start, end } = self.range; + if self.vec.len() == self.orig_len { + // We must not have produced, so just call a normal drain to remove the items. + self.vec.drain(start..end); + } else if start == end { + // Empty range, so just restore the length to its original state + unsafe { + self.vec.set_len(self.orig_len); + } + } else if end < self.orig_len { + // The producer was responsible for consuming the drained items. + // Move the tail items to their new place, then set the length to include them. + unsafe { + let ptr = self.vec.as_mut_ptr().add(start); + let tail_ptr = self.vec.as_ptr().add(end); + let tail_len = self.orig_len - end; + ptr::copy(tail_ptr, ptr, tail_len); + self.vec.set_len(start + tail_len); } } } @@ -181,7 +183,7 @@ pub(crate) struct DrainProducer<'data, T: Send> { impl<T: Send> DrainProducer<'_, T> { /// Creates a draining producer, which *moves* items from the slice. /// - /// Unsafe bacause `!Copy` data must not be read after the borrow is released. + /// Unsafe because `!Copy` data must not be read after the borrow is released. pub(crate) unsafe fn new(slice: &mut [T]) -> DrainProducer<'_, T> { DrainProducer { slice } } @@ -207,7 +209,7 @@ impl<'data, T: 'data + Send> Producer for DrainProducer<'data, T> { fn into_iter(mut self) -> Self::IntoIter { // replace the slice so we don't drop it twice - let slice = mem::replace(&mut self.slice, &mut []); + let slice = mem::take(&mut self.slice); SliceDrain { iter: slice.iter_mut(), } @@ -215,7 +217,7 @@ impl<'data, T: 'data + Send> Producer for DrainProducer<'data, T> { fn split_at(mut self, index: usize) -> (Self, Self) { // replace the slice so we don't drop it twice - let slice = mem::replace(&mut self.slice, &mut []); + let slice = mem::take(&mut self.slice); let (left, right) = slice.split_at_mut(index); unsafe { (DrainProducer::new(left), DrainProducer::new(right)) } } diff --git a/vendor/rayon/tests/clones.rs b/vendor/rayon/tests/clones.rs index 2f512ca05..2b78f0987 100644 --- a/vendor/rayon/tests/clones.rs +++ b/vendor/rayon/tests/clones.rs @@ -130,6 +130,12 @@ fn clone_adaptors() { check(v.par_iter().flatten_iter()); check(v.par_iter().with_max_len(1).fold(|| 0, |x, _| x)); check(v.par_iter().with_max_len(1).fold_with(0, |x, _| x)); + check(v.par_iter().with_max_len(1).fold_chunks(1, || 0, |x, _| x)); + check( + v.par_iter() + .with_max_len(1) + .fold_chunks_with(1, 0, |x, _| x), + ); check(v.par_iter().with_max_len(1).try_fold(|| 0, |_, &x| x)); check(v.par_iter().with_max_len(1).try_fold_with(0, |_, &x| x)); check(v.par_iter().inspect(|_| ())); diff --git a/vendor/rayon/tests/debug.rs b/vendor/rayon/tests/debug.rs index d107b1377..1cbf4e6ed 100644 --- a/vendor/rayon/tests/debug.rs +++ b/vendor/rayon/tests/debug.rs @@ -155,6 +155,8 @@ fn debug_adaptors() { check(v.par_iter().map(Some).flatten_iter()); check(v.par_iter().fold(|| 0, |x, _| x)); check(v.par_iter().fold_with(0, |x, _| x)); + check(v.par_iter().fold_chunks(3, || 0, |x, _| x)); + check(v.par_iter().fold_chunks_with(3, 0, |x, _| x)); check(v.par_iter().try_fold(|| 0, |x, _| Some(x))); check(v.par_iter().try_fold_with(0, |x, _| Some(x))); check(v.par_iter().inspect(|_| ())); diff --git a/vendor/rayon/tests/drain_vec.rs b/vendor/rayon/tests/drain_vec.rs new file mode 100644 index 000000000..08f1120b7 --- /dev/null +++ b/vendor/rayon/tests/drain_vec.rs @@ -0,0 +1,41 @@ +use rayon::prelude::*; + +#[test] +fn drain_vec_yielded() { + let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let yielded = vec_org.par_drain(0..5).collect::<Vec<_>>(); + + assert_eq!(&yielded, &[0, 1, 2, 3, 4]); + assert_eq!(&vec_org, &[5, 6, 7, 8, 9]); +} + +#[test] +fn drain_vec_dropped() { + let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let yielded = vec_org.par_drain(0..5); + + drop(yielded); + assert_eq!(&vec_org, &[5, 6, 7, 8, 9]); +} + +#[test] +fn drain_vec_empty_range_yielded() { + let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let yielded = vec_org.par_drain(5..5).collect::<Vec<_>>(); + + assert_eq!(&yielded, &[]); + assert_eq!(&vec_org, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +} + +#[test] +fn drain_vec_empty_range_dropped() { + let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let yielded = vec_org.par_drain(5..5); + + drop(yielded); + assert_eq!(&vec_org, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +} diff --git a/vendor/rayon/tests/iter_panic.rs b/vendor/rayon/tests/iter_panic.rs index 4885a28be..37d4d6a3a 100644 --- a/vendor/rayon/tests/iter_panic.rs +++ b/vendor/rayon/tests/iter_panic.rs @@ -47,6 +47,6 @@ fn iter_panic_fuse() { assert!(count(iter.clone().panic_fuse().inspect(check)) < expected); // Try in reverse to be sure we hit the producer case. - assert!(count(iter.clone().panic_fuse().inspect(check).rev()) < expected); + assert!(count(iter.panic_fuse().inspect(check).rev()) < expected); }); } |