diff --git a/Cargo.toml b/Cargo.toml index c18dfce2..01eedc22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ bench = false autocfg = "1" [dependencies] serde = { version = "1.0", optional = true, default-features = false } -rayon = { version = "1.2", optional = true } +rayon = { version = "1.4.1", optional = true } # Internal feature, only used when building as part of rustc, # not part of the stable interface of this crate. diff --git a/src/map.rs b/src/map.rs index 830df9e8..206e7eef 100644 --- a/src/map.rs +++ b/src/map.rs @@ -69,12 +69,12 @@ pub use self::core::{Entry, OccupiedEntry, VacantEntry}; /// ``` #[cfg(has_std)] pub struct IndexMap { - core: IndexMapCore, + pub(crate) core: IndexMapCore, hash_builder: S, } #[cfg(not(has_std))] pub struct IndexMap { - core: IndexMapCore, + pub(crate) core: IndexMapCore, hash_builder: S, } diff --git a/src/map/core.rs b/src/map/core.rs index c5ad4f04..bfd571d9 100644 --- a/src/map/core.rs +++ b/src/map/core.rs @@ -166,6 +166,19 @@ impl IndexMapCore { self.entries.drain(range) } + #[cfg(feature = "rayon")] + pub(crate) fn par_drain(&mut self, range: R) -> rayon::vec::Drain<'_, Bucket> + where + K: Send, + V: Send, + R: RangeBounds, + { + use rayon::iter::ParallelDrainRange; + let range = simplify_range(range, self.entries.len()); + self.erase_indices(range.start, range.end); + self.entries.par_drain(range) + } + pub(crate) fn split_off(&mut self, at: usize) -> Self { assert!(at <= self.entries.len()); self.erase_indices(at, self.entries.len()); diff --git a/src/rayon/map.rs b/src/rayon/map.rs index bedad3c4..e4d9befd 100644 --- a/src/rayon/map.rs +++ b/src/rayon/map.rs @@ -13,6 +13,7 @@ use crate::vec::Vec; use core::cmp::Ordering; use core::fmt; use core::hash::{BuildHasher, Hash}; +use core::ops::RangeBounds; use crate::Bucket; use crate::Entries; @@ -156,6 +157,43 @@ impl IndexedParallelIterator for ParIterMut<'_, K, V> { indexed_parallel_iterator_methods!(Bucket::ref_mut); } +/// Requires crate feature `"rayon"`. +impl<'a, K, V, S> ParallelDrainRange for &'a mut IndexMap +where + K: Send, + V: Send, +{ + type Item = (K, V); + type Iter = ParDrain<'a, K, V>; + + fn par_drain>(self, range: R) -> Self::Iter { + ParDrain { + entries: self.core.par_drain(range), + } + } +} + +/// A parallel draining iterator over the entries of a `IndexMap`. +/// +/// This `struct` is created by the [`par_drain`] method on [`IndexMap`] +/// (provided by rayon's `ParallelDrainRange` trait). See its documentation for more. +/// +/// [`par_drain`]: ../struct.IndexMap.html#method.par_drain +/// [`IndexMap`]: ../struct.IndexMap.html +pub struct ParDrain<'a, K: Send, V: Send> { + entries: rayon::vec::Drain<'a, Bucket>, +} + +impl ParallelIterator for ParDrain<'_, K, V> { + type Item = (K, V); + + parallel_iterator_methods!(Bucket::key_value); +} + +impl IndexedParallelIterator for ParDrain<'_, K, V> { + indexed_parallel_iterator_methods!(Bucket::key_value); +} + /// Parallel iterator methods and other parallel methods. /// /// The following methods **require crate feature `"rayon"`**. diff --git a/src/rayon/set.rs b/src/rayon/set.rs index f3e0da91..1ca0945d 100644 --- a/src/rayon/set.rs +++ b/src/rayon/set.rs @@ -13,6 +13,7 @@ use crate::vec::Vec; use core::cmp::Ordering; use core::fmt; use core::hash::{BuildHasher, Hash}; +use core::ops::RangeBounds; use crate::Entries; use crate::IndexSet; @@ -111,6 +112,42 @@ impl IndexedParallelIterator for ParIter<'_, T> { indexed_parallel_iterator_methods!(Bucket::key_ref); } +/// Requires crate feature `"rayon"`. +impl<'a, T, S> ParallelDrainRange for &'a mut IndexSet +where + T: Send, +{ + type Item = T; + type Iter = ParDrain<'a, T>; + + fn par_drain>(self, range: R) -> Self::Iter { + ParDrain { + entries: self.map.core.par_drain(range), + } + } +} + +/// A parallel draining iterator over the items of a `IndexSet`. +/// +/// This `struct` is created by the [`par_drain`] method on [`IndexSet`] +/// (provided by rayon's `ParallelDrainRange` trait). See its documentation for more. +/// +/// [`par_drain`]: ../struct.IndexSet.html#method.par_drain +/// [`IndexSet`]: ../struct.IndexSet.html +pub struct ParDrain<'a, T: Send> { + entries: rayon::vec::Drain<'a, Bucket>, +} + +impl ParallelIterator for ParDrain<'_, T> { + type Item = T; + + parallel_iterator_methods!(Bucket::key); +} + +impl IndexedParallelIterator for ParDrain<'_, T> { + indexed_parallel_iterator_methods!(Bucket::key); +} + /// Parallel iterator methods and other parallel methods. /// /// The following methods **require crate feature `"rayon"`**. diff --git a/src/set.rs b/src/set.rs index 348129c8..5aabcf51 100644 --- a/src/set.rs +++ b/src/set.rs @@ -61,11 +61,11 @@ type Bucket = super::Bucket; /// ``` #[cfg(has_std)] pub struct IndexSet { - map: IndexMap, + pub(crate) map: IndexMap, } #[cfg(not(has_std))] pub struct IndexSet { - map: IndexMap, + pub(crate) map: IndexMap, } impl Clone for IndexSet