1 use crate::lock
::RwLock
;
2 use crate::mapref
::multiple
::{RefMulti, RefMutMulti}
;
4 use crate::{DashMap, HashMap}
;
5 use core
::hash
::{BuildHasher, Hash}
;
6 use rayon
::iter
::plumbing
::UnindexedConsumer
;
7 use rayon
::iter
::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}
;
8 use std
::collections
::hash_map
::RandomState
;
11 impl<K
, V
, S
> ParallelExtend
<(K
, V
)> for DashMap
<K
, V
, S
>
13 K
: Send
+ Sync
+ Eq
+ Hash
,
15 S
: Send
+ Sync
+ Clone
+ BuildHasher
,
17 fn par_extend
<I
>(&mut self, par_iter
: I
)
19 I
: IntoParallelIterator
<Item
= (K
, V
)>,
21 (&*self).par_extend(par_iter
);
25 // Since we don't actually need mutability, we can implement this on a
26 // reference, similar to `io::Write for &File`.
27 impl<K
, V
, S
> ParallelExtend
<(K
, V
)> for &'_ DashMap
<K
, V
, S
>
29 K
: Send
+ Sync
+ Eq
+ Hash
,
31 S
: Send
+ Sync
+ Clone
+ BuildHasher
,
33 fn par_extend
<I
>(&mut self, par_iter
: I
)
35 I
: IntoParallelIterator
<Item
= (K
, V
)>,
38 par_iter
.into_par_iter().for_each(move |(key
, value
)| {
39 map
.insert(key
, value
);
44 impl<K
, V
, S
> FromParallelIterator
<(K
, V
)> for DashMap
<K
, V
, S
>
46 K
: Send
+ Sync
+ Eq
+ Hash
,
48 S
: Send
+ Sync
+ Clone
+ Default
+ BuildHasher
,
50 fn from_par_iter
<I
>(par_iter
: I
) -> Self
52 I
: IntoParallelIterator
<Item
= (K
, V
)>,
54 let map
= Self::default();
55 (&map
).par_extend(par_iter
);
60 // Implementation note: while the shards will iterate in parallel, we flatten
61 // sequentially within each shard (`flat_map_iter`), because the standard
62 // `HashMap` only implements `ParallelIterator` by collecting to a `Vec` first.
63 // There is real parallel support in the `hashbrown/rayon` feature, but we don't
64 // always use that map.
66 impl<K
, V
, S
> IntoParallelIterator
for DashMap
<K
, V
, S
>
70 S
: Send
+ Clone
+ BuildHasher
,
72 type Iter
= OwningIter
<K
, V
, S
>;
75 fn into_par_iter(self) -> Self::Iter
{
82 pub struct OwningIter
<K
, V
, S
= RandomState
> {
83 shards
: Box
<[RwLock
<HashMap
<K
, V
, S
>>]>,
86 impl<K
, V
, S
> ParallelIterator
for OwningIter
<K
, V
, S
>
90 S
: Send
+ Clone
+ BuildHasher
,
94 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
96 C
: UnindexedConsumer
<Self::Item
>,
98 Vec
::from(self.shards
)
100 .flat_map_iter(|shard
| {
104 .map(|(k
, v
)| (k
, v
.into_inner()))
106 .drive_unindexed(consumer
)
110 // This impl also enables `IntoParallelRefIterator::par_iter`
111 impl<'a
, K
, V
, S
> IntoParallelIterator
for &'a DashMap
<K
, V
, S
>
113 K
: Send
+ Sync
+ Eq
+ Hash
,
115 S
: Send
+ Sync
+ Clone
+ BuildHasher
,
117 type Iter
= Iter
<'a
, K
, V
, S
>;
118 type Item
= RefMulti
<'a
, K
, V
, S
>;
120 fn into_par_iter(self) -> Self::Iter
{
122 shards
: &self.shards
,
127 pub struct Iter
<'a
, K
, V
, S
= RandomState
> {
128 shards
: &'a
[RwLock
<HashMap
<K
, V
, S
>>],
131 impl<'a
, K
, V
, S
> ParallelIterator
for Iter
<'a
, K
, V
, S
>
133 K
: Send
+ Sync
+ Eq
+ Hash
,
135 S
: Send
+ Sync
+ Clone
+ BuildHasher
,
137 type Item
= RefMulti
<'a
, K
, V
, S
>;
139 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
141 C
: UnindexedConsumer
<Self::Item
>,
145 .flat_map_iter(|shard
| {
146 let guard
= shard
.read();
147 let sref
: &'a HashMap
<K
, V
, S
> = unsafe { util::change_lifetime_const(&*guard) }
;
149 let guard
= Arc
::new(guard
);
150 sref
.iter().map(move |(k
, v
)| {
151 let guard
= Arc
::clone(&guard
);
152 unsafe { RefMulti::new(guard, k, v.get()) }
155 .drive_unindexed(consumer
)
159 // This impl also enables `IntoParallelRefMutIterator::par_iter_mut`
160 impl<'a
, K
, V
, S
> IntoParallelIterator
for &'a
mut DashMap
<K
, V
, S
>
162 K
: Send
+ Sync
+ Eq
+ Hash
,
164 S
: Send
+ Sync
+ Clone
+ BuildHasher
,
166 type Iter
= IterMut
<'a
, K
, V
, S
>;
167 type Item
= RefMutMulti
<'a
, K
, V
, S
>;
169 fn into_par_iter(self) -> Self::Iter
{
171 shards
: &self.shards
,
176 impl<'a
, K
, V
, S
> DashMap
<K
, V
, S
>
178 K
: Send
+ Sync
+ Eq
+ Hash
,
180 S
: Send
+ Sync
+ Clone
+ BuildHasher
,
182 // Unlike `IntoParallelRefMutIterator::par_iter_mut`, we only _need_ `&self`.
183 pub fn par_iter_mut(&self) -> IterMut
<'_
, K
, V
, S
> {
185 shards
: &self.shards
,
190 pub struct IterMut
<'a
, K
, V
, S
= RandomState
> {
191 shards
: &'a
[RwLock
<HashMap
<K
, V
, S
>>],
194 impl<'a
, K
, V
, S
> ParallelIterator
for IterMut
<'a
, K
, V
, S
>
196 K
: Send
+ Sync
+ Eq
+ Hash
,
198 S
: Send
+ Sync
+ Clone
+ BuildHasher
,
200 type Item
= RefMutMulti
<'a
, K
, V
, S
>;
202 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
204 C
: UnindexedConsumer
<Self::Item
>,
208 .flat_map_iter(|shard
| {
209 let mut guard
= shard
.write();
210 let sref
: &'a
mut HashMap
<K
, V
, S
> =
211 unsafe { util::change_lifetime_mut(&mut *guard) }
;
213 let guard
= Arc
::new(guard
);
214 sref
.iter_mut().map(move |(k
, v
)| {
215 let guard
= Arc
::clone(&guard
);
216 unsafe { RefMutMulti::new(guard, k, v.get_mut()) }
219 .drive_unindexed(consumer
)