1 use crate::raw
::Bucket
;
2 use crate::raw
::{RawIter, RawIterRange, RawTable}
;
3 use crate::scopeguard
::guard
;
4 use alloc
::alloc
::dealloc
;
5 use core
::marker
::PhantomData
;
7 use core
::ptr
::NonNull
;
9 plumbing
::{self, Folder, UnindexedConsumer, UnindexedProducer}
,
13 /// Parallel iterator which returns a raw pointer to every full bucket in the table.
14 pub struct RawParIter
<T
> {
15 iter
: RawIterRange
<T
>,
18 impl<T
> From
<RawIter
<T
>> for RawParIter
<T
> {
19 fn from(it
: RawIter
<T
>) -> Self {
20 RawParIter { iter: it.iter }
24 impl<T
> ParallelIterator
for RawParIter
<T
> {
25 type Item
= Bucket
<T
>;
27 #[cfg_attr(feature = "inline-more", inline)]
28 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
30 C
: UnindexedConsumer
<Self::Item
>,
32 let producer
= ParIterProducer { iter: self.iter }
;
33 plumbing
::bridge_unindexed(producer
, consumer
)
37 /// Producer which returns a `Bucket<T>` for every element.
38 struct ParIterProducer
<T
> {
39 iter
: RawIterRange
<T
>,
42 impl<T
> UnindexedProducer
for ParIterProducer
<T
> {
43 type Item
= Bucket
<T
>;
45 #[cfg_attr(feature = "inline-more", inline)]
46 fn split(self) -> (Self, Option
<Self>) {
47 let (left
, right
) = self.iter
.split();
48 let left
= ParIterProducer { iter: left }
;
49 let right
= right
.map(|right
| ParIterProducer { iter: right }
);
53 #[cfg_attr(feature = "inline-more", inline)]
54 fn fold_with
<F
>(self, folder
: F
) -> F
56 F
: Folder
<Self::Item
>,
58 folder
.consume_iter(self.iter
)
62 /// Parallel iterator which consumes a table and returns elements.
63 pub struct RawIntoParIter
<T
> {
67 impl<T
: Send
> ParallelIterator
for RawIntoParIter
<T
> {
70 #[cfg_attr(feature = "inline-more", inline)]
71 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
73 C
: UnindexedConsumer
<Self::Item
>,
75 let iter
= unsafe { self.table.iter().iter }
;
76 let _guard
= guard(self.table
.into_alloc(), |alloc
| {
77 if let Some((ptr
, layout
)) = *alloc
{
79 dealloc(ptr
.as_ptr(), layout
);
83 let producer
= ParDrainProducer { iter }
;
84 plumbing
::bridge_unindexed(producer
, consumer
)
88 /// Parallel iterator which consumes elements without freeing the table storage.
89 pub struct RawParDrain
<'a
, T
> {
90 // We don't use a &'a mut RawTable<T> because we want RawParDrain to be
92 table
: NonNull
<RawTable
<T
>>,
93 marker
: PhantomData
<&'a RawTable
<T
>>,
96 unsafe impl<T
> Send
for RawParDrain
<'_
, T
> {}
98 impl<T
: Send
> ParallelIterator
for RawParDrain
<'_
, T
> {
101 #[cfg_attr(feature = "inline-more", inline)]
102 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
104 C
: UnindexedConsumer
<Self::Item
>,
106 let _guard
= guard(self.table
, |table
| unsafe {
107 table
.as_mut().clear_no_drop()
109 let iter
= unsafe { self.table.as_ref().iter().iter }
;
111 let producer
= ParDrainProducer { iter }
;
112 plumbing
::bridge_unindexed(producer
, consumer
)
116 impl<T
> Drop
for RawParDrain
<'_
, T
> {
118 // If drive_unindexed is not called then simply clear the table.
119 unsafe { self.table.as_mut().clear() }
123 /// Producer which will consume all elements in the range, even if it is dropped
125 struct ParDrainProducer
<T
> {
126 iter
: RawIterRange
<T
>,
129 impl<T
: Send
> UnindexedProducer
for ParDrainProducer
<T
> {
132 #[cfg_attr(feature = "inline-more", inline)]
133 fn split(self) -> (Self, Option
<Self>) {
134 let (left
, right
) = self.iter
.clone().split();
136 let left
= ParDrainProducer { iter: left }
;
137 let right
= right
.map(|right
| ParDrainProducer { iter: right }
);
141 #[cfg_attr(feature = "inline-more", inline)]
142 fn fold_with
<F
>(mut self, mut folder
: F
) -> F
144 F
: Folder
<Self::Item
>,
146 // Make sure to modify the iterator in-place so that any remaining
147 // elements are processed in our Drop impl.
148 while let Some(item
) = self.iter
.next() {
149 folder
= folder
.consume(unsafe { item.read() }
);
155 // If we processed all elements then we don't need to run the drop.
161 impl<T
> Drop
for ParDrainProducer
<T
> {
162 #[cfg_attr(feature = "inline-more", inline)]
164 // Drop all remaining elements
165 if mem
::needs_drop
::<T
>() {
166 while let Some(item
) = self.iter
.next() {
175 impl<T
> RawTable
<T
> {
176 /// Returns a parallel iterator over the elements in a `RawTable`.
177 #[cfg_attr(feature = "inline-more", inline)]
178 pub unsafe fn par_iter(&self) -> RawParIter
<T
> {
180 iter
: self.iter().iter
,
184 /// Returns a parallel iterator over the elements in a `RawTable`.
185 #[cfg_attr(feature = "inline-more", inline)]
186 pub fn into_par_iter(self) -> RawIntoParIter
<T
> {
187 RawIntoParIter { table: self }
190 /// Returns a parallel iterator which consumes all elements of a `RawTable`
191 /// without freeing its memory allocation.
192 #[cfg_attr(feature = "inline-more", inline)]
193 pub fn par_drain(&mut self) -> RawParDrain
<'_
, T
> {
195 table
: NonNull
::from(self),