diff --git a/Cargo.toml b/Cargo.toml index 3dd659db4..798901b5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc-rayon" -version = "0.5.0" +version = "0.5.1" authors = ["Niko Matsakis ", "Josh Stone "] description = "Simple work-stealing parallelism for Rust - fork for rustc" @@ -22,6 +22,7 @@ exclude = ["ci"] name = "rayon" [dependencies] +indexmap = { version = "2", optional = true } rustc-rayon-core = { version = "0.5", path = "rayon-core" } # This is a public dependency! diff --git a/src/lib.rs b/src/lib.rs index 86f997b36..7ba0a9b3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -110,6 +110,7 @@ pub mod vec; mod math; mod par_either; +mod par_indexmap; mod compile_fail; diff --git a/src/par_indexmap.rs b/src/par_indexmap.rs new file mode 100644 index 000000000..fb03ac18d --- /dev/null +++ b/src/par_indexmap.rs @@ -0,0 +1,230 @@ +#![cfg(feature = "indexmap")] +//! Minimal `indexmap` support for `rustc-rayon` + +use crate::iter::plumbing::{bridge, Consumer, Producer, ProducerCallback, UnindexedConsumer}; +use crate::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; + +mod map { + use super::*; + use indexmap::map::{IndexMap, Iter, IterMut, Slice}; + + impl<'a, K, V, S> IntoParallelIterator for &'a IndexMap + where + K: Sync, + V: Sync, + { + type Item = (&'a K, &'a V); + type Iter = ParIter<'a, K, V>; + + fn into_par_iter(self) -> Self::Iter { + ParIter { + slice: self.as_slice(), + } + } + } + + #[derive(Debug)] + pub struct ParIter<'a, K, V> { + slice: &'a Slice, + } + + impl<'a, K: Sync, V: Sync> ParallelIterator for ParIter<'a, K, V> { + type Item = (&'a K, &'a V); + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: UnindexedConsumer, + { + bridge(self, consumer) + } + + fn opt_len(&self) -> Option { + Some(self.slice.len()) + } + } + + impl IndexedParallelIterator for ParIter<'_, K, V> { + fn drive(self, consumer: C) -> C::Result + where + C: Consumer, + { + bridge(self, consumer) + } + + fn len(&self) -> usize { + self.slice.len() + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: ProducerCallback, + { + callback.callback(IterProducer { slice: self.slice }) + } + } + + struct IterProducer<'a, K, V> { + slice: &'a Slice, + } + + impl<'a, K: Sync, V: Sync> Producer for IterProducer<'a, K, V> { + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + + fn into_iter(self) -> Self::IntoIter { + self.slice.iter() + } + + fn split_at(self, index: usize) -> (Self, Self) { + let (left, right) = self.slice.split_at(index); + (Self { slice: left }, Self { slice: right }) + } + } + + impl<'a, K, V, S> IntoParallelIterator for &'a mut IndexMap + where + K: Sync + Send, + V: Send, + { + type Item = (&'a K, &'a mut V); + type Iter = ParIterMut<'a, K, V>; + + fn into_par_iter(self) -> Self::Iter { + ParIterMut { + slice: self.as_mut_slice(), + } + } + } + + #[derive(Debug)] + pub struct ParIterMut<'a, K, V> { + slice: &'a mut Slice, + } + + impl<'a, K: Sync + Send, V: Send> ParallelIterator for ParIterMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: UnindexedConsumer, + { + bridge(self, consumer) + } + + fn opt_len(&self) -> Option { + Some(self.slice.len()) + } + } + + impl IndexedParallelIterator for ParIterMut<'_, K, V> { + fn drive(self, consumer: C) -> C::Result + where + C: Consumer, + { + bridge(self, consumer) + } + + fn len(&self) -> usize { + self.slice.len() + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: ProducerCallback, + { + callback.callback(IterMutProducer { slice: self.slice }) + } + } + + struct IterMutProducer<'a, K, V> { + slice: &'a mut Slice, + } + + impl<'a, K: Sync + Send, V: Send> Producer for IterMutProducer<'a, K, V> { + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + + fn into_iter(self) -> Self::IntoIter { + self.slice.iter_mut() + } + + fn split_at(self, index: usize) -> (Self, Self) { + let (left, right) = self.slice.split_at_mut(index); + (Self { slice: left }, Self { slice: right }) + } + } +} + +mod set { + use super::*; + use indexmap::set::{IndexSet, Iter, Slice}; + + impl<'a, T: Sync, S> IntoParallelIterator for &'a IndexSet { + type Item = &'a T; + type Iter = ParIter<'a, T>; + + fn into_par_iter(self) -> Self::Iter { + ParIter { + slice: self.as_slice(), + } + } + } + + #[derive(Debug)] + pub struct ParIter<'a, T> { + slice: &'a Slice, + } + + impl<'a, T: Sync> ParallelIterator for ParIter<'a, T> { + type Item = &'a T; + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: UnindexedConsumer, + { + bridge(self, consumer) + } + + fn opt_len(&self) -> Option { + Some(self.slice.len()) + } + } + + impl IndexedParallelIterator for ParIter<'_, T> { + fn drive(self, consumer: C) -> C::Result + where + C: Consumer, + { + bridge(self, consumer) + } + + fn len(&self) -> usize { + self.slice.len() + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: ProducerCallback, + { + callback.callback(IterProducer { slice: self.slice }) + } + } + + struct IterProducer<'a, T> { + slice: &'a Slice, + } + + impl<'a, T: Sync> Producer for IterProducer<'a, T> { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.slice.iter() + } + + fn split_at(self, index: usize) -> (Self, Self) { + let (left, right) = self.slice.split_at(index); + (Self { slice: left }, Self { slice: right }) + } + } +}