1
- use alloc:: alloc:: { dealloc, Layout } ;
1
+ use alloc:: alloc:: dealloc;
2
+ use core:: marker:: PhantomData ;
2
3
use core:: mem;
3
4
use core:: ptr:: NonNull ;
4
5
use raw:: Bucket ;
@@ -58,8 +59,7 @@ impl<T> UnindexedProducer for ParIterProducer<T> {
58
59
59
60
/// Parallel iterator which consumes a table and returns elements.
60
61
pub struct RawIntoParIter < T > {
61
- iter : RawIterRange < T > ,
62
- alloc : Option < ( NonNull < u8 > , Layout ) > ,
62
+ table : RawTable < T > ,
63
63
}
64
64
65
65
unsafe impl < T > Send for RawIntoParIter < T > { }
@@ -72,21 +72,25 @@ impl<T: Send> ParallelIterator for RawIntoParIter<T> {
72
72
where
73
73
C : UnindexedConsumer < Self :: Item > ,
74
74
{
75
- let _guard = guard ( self . alloc , |alloc| {
75
+ let iter = unsafe { self . table . iter ( ) . iter } ;
76
+ let _guard = guard ( self . table . into_alloc ( ) , |alloc| {
76
77
if let Some ( ( ptr, layout) ) = * alloc {
77
78
unsafe {
78
79
dealloc ( ptr. as_ptr ( ) , layout) ;
79
80
}
80
81
}
81
82
} ) ;
82
- let producer = ParDrainProducer { iter : self . iter } ;
83
+ let producer = ParDrainProducer { iter } ;
83
84
plumbing:: bridge_unindexed ( producer, consumer)
84
85
}
85
86
}
86
87
87
88
/// Parallel iterator which consumes elements without freeing the table storage.
88
89
pub struct RawParDrain < ' a , T > {
89
- table : & ' a mut RawTable < T > ,
90
+ // We don't use a &'a RawTable<T> because we want RawParDrain to be
91
+ // covariant over 'a.
92
+ table : NonNull < RawTable < T > > ,
93
+ _marker : PhantomData < & ' a RawTable < T > > ,
90
94
}
91
95
92
96
unsafe impl < ' a , T > Send for RawParDrain < ' a , T > { }
@@ -99,13 +103,23 @@ impl<'a, T: Send> ParallelIterator for RawParDrain<'a, T> {
99
103
where
100
104
C : UnindexedConsumer < Self :: Item > ,
101
105
{
102
- let iter = unsafe { self . table . iter ( ) . iter } ;
103
- let _guard = guard ( self . table , |table| table. clear_no_drop ( ) ) ;
106
+ let _guard = guard ( self . table , |table| unsafe {
107
+ table. as_mut ( ) . clear_no_drop ( )
108
+ } ) ;
109
+ let iter = unsafe { self . table . as_ref ( ) . iter ( ) . iter } ;
110
+ mem:: forget ( self ) ;
104
111
let producer = ParDrainProducer { iter } ;
105
112
plumbing:: bridge_unindexed ( producer, consumer)
106
113
}
107
114
}
108
115
116
+ impl < ' a , T > Drop for RawParDrain < ' a , T > {
117
+ fn drop ( & mut self ) {
118
+ // If drive_unindexed is not called then simply clear the table.
119
+ unsafe { self . table . as_mut ( ) . clear ( ) }
120
+ }
121
+ }
122
+
109
123
/// Producer which will consume all elements in the range, even if it is dropped
110
124
/// halfway through.
111
125
struct ParDrainProducer < T > {
@@ -136,20 +150,23 @@ impl<T: Send> UnindexedProducer for ParDrainProducer<T> {
136
150
while let Some ( item) = self . iter . next ( ) {
137
151
folder = folder. consume ( unsafe { item. read ( ) } ) ;
138
152
if folder. full ( ) {
139
- break ;
153
+ return folder ;
140
154
}
141
155
}
156
+
157
+ // If we processed all elements then we don't need to run the drop.
158
+ mem:: forget ( self ) ;
142
159
folder
143
160
}
144
161
}
145
162
146
163
impl < T > Drop for ParDrainProducer < T > {
147
164
#[ inline]
148
165
fn drop ( & mut self ) {
149
- unsafe {
150
- // Drop all remaining elements
151
- if mem :: needs_drop :: < T > ( ) {
152
- while let Some ( item ) = self . iter . next ( ) {
166
+ // Drop all remaining elements
167
+ if mem :: needs_drop :: < T > ( ) {
168
+ while let Some ( item ) = self . iter . next ( ) {
169
+ unsafe {
153
170
item. drop ( ) ;
154
171
}
155
172
}
@@ -169,16 +186,16 @@ impl<T> RawTable<T> {
169
186
/// Returns a parallel iterator over the elements in a `RawTable`.
170
187
#[ inline]
171
188
pub fn into_par_iter ( self ) -> RawIntoParIter < T > {
172
- RawIntoParIter {
173
- iter : unsafe { self . iter ( ) . iter } ,
174
- alloc : self . into_alloc ( ) ,
175
- }
189
+ RawIntoParIter { table : self }
176
190
}
177
191
178
192
/// Returns a parallel iterator which consumes all elements of a `RawTable`
179
193
/// without freeing its memory allocation.
180
194
#[ inline]
181
195
pub fn par_drain ( & mut self ) -> RawParDrain < T > {
182
- RawParDrain { table : self }
196
+ RawParDrain {
197
+ table : NonNull :: from ( self ) ,
198
+ _marker : PhantomData ,
199
+ }
183
200
}
184
201
}
0 commit comments