@@ -5,6 +5,7 @@ use std::convert::TryInto;
5
5
use std:: fmt:: Debug ;
6
6
use std:: hash:: { Hash , Hasher } ;
7
7
use std:: io:: { Read , Seek , SeekFrom , Write } ;
8
+ use std:: mem:: ManuallyDrop ;
8
9
9
10
use crate :: frames:: UnresolvedFrames ;
10
11
@@ -148,6 +149,7 @@ pub struct TempFdArray<T: 'static> {
148
149
file : NamedTempFile ,
149
150
buffer : Box < [ T ; BUFFER_LENGTH ] > ,
150
151
buffer_index : usize ,
152
+ flush_n : usize ,
151
153
}
152
154
153
155
impl < T : Default + Debug > TempFdArray < T > {
@@ -162,6 +164,7 @@ impl<T: Default + Debug> TempFdArray<T> {
162
164
file,
163
165
buffer,
164
166
buffer_index : 0 ,
167
+ flush_n : 0 ,
165
168
} )
166
169
}
167
170
}
@@ -175,6 +178,7 @@ impl<T> TempFdArray<T> {
175
178
BUFFER_LENGTH * std:: mem:: size_of :: < T > ( ) ,
176
179
)
177
180
} ;
181
+ self . flush_n += 1 ;
178
182
self . file . write_all ( buf) ?;
179
183
180
184
Ok ( ( ) )
@@ -191,24 +195,56 @@ impl<T> TempFdArray<T> {
191
195
Ok ( ( ) )
192
196
}
193
197
194
- fn try_iter ( & self ) -> std :: io :: Result < impl Iterator < Item = & T > > {
195
- let mut file_vec = Vec :: new ( ) ;
196
- let mut file = self . file . reopen ( ) ? ;
197
- file . seek ( SeekFrom :: Start ( 0 ) ) ? ;
198
- file . read_to_end ( & mut file_vec ) ?;
199
- file . seek ( SeekFrom :: End ( 0 ) ) ? ;
198
+ fn try_iter < ' lt > (
199
+ & ' lt self ,
200
+ file_buffer_container : & ' lt mut Option < Box < [ ManuallyDrop < T > ] > > ,
201
+ ) -> std :: io :: Result < impl Iterator < Item = & ' lt T > > {
202
+ let file_buffer = self . file_buffer ( ) ?;
203
+ let file_buffer = file_buffer_container . insert ( file_buffer ) ;
200
204
201
205
Ok ( TempFdArrayIterator {
202
206
buffer : & self . buffer [ 0 ..self . buffer_index ] ,
203
- file_vec ,
207
+ file_buffer ,
204
208
index : 0 ,
205
209
} )
206
210
}
211
+
212
+ fn file_buffer ( & self ) -> std:: io:: Result < Box < [ ManuallyDrop < T > ] > > {
213
+ if self . flush_n == 0 {
214
+ return Ok ( Vec :: new ( ) . into_boxed_slice ( ) ) ;
215
+ }
216
+
217
+ let mut file = self . file . reopen ( ) ?;
218
+ file. seek ( SeekFrom :: Start ( 0 ) ) ?;
219
+ let file_buffer = unsafe {
220
+ // Get properly aligned pointer
221
+ let len = BUFFER_LENGTH * self . flush_n ;
222
+ // Expect T to be non-ZST
223
+ let layout = std:: alloc:: Layout :: array :: < ManuallyDrop < T > > ( len) . unwrap ( ) ;
224
+ let ptr = std:: alloc:: alloc ( layout) ;
225
+ if ptr. is_null ( ) {
226
+ std:: alloc:: handle_alloc_error ( layout) ;
227
+ }
228
+ // Populate with bytes
229
+ file. read_exact ( std:: slice:: from_raw_parts_mut (
230
+ ptr,
231
+ len * std:: mem:: size_of :: < T > ( ) ,
232
+ ) ) ?;
233
+ // Cast to proper type
234
+ Box :: from_raw ( std:: ptr:: slice_from_raw_parts_mut (
235
+ ptr. cast :: < ManuallyDrop < T > > ( ) ,
236
+ len,
237
+ ) )
238
+ } ;
239
+ file. seek ( SeekFrom :: End ( 0 ) ) ?;
240
+
241
+ Ok ( file_buffer)
242
+ }
207
243
}
208
244
209
245
pub struct TempFdArrayIterator < ' a , T > {
210
246
pub buffer : & ' a [ T ] ,
211
- pub file_vec : Vec < u8 > ,
247
+ pub file_buffer : & ' a [ ManuallyDrop < T > ] ,
212
248
pub index : usize ,
213
249
}
214
250
@@ -219,16 +255,11 @@ impl<'a, T> Iterator for TempFdArrayIterator<'a, T> {
219
255
if self . index < self . buffer . len ( ) {
220
256
self . index += 1 ;
221
257
Some ( & self . buffer [ self . index - 1 ] )
258
+ } else if self . index - self . buffer . len ( ) < self . file_buffer . len ( ) {
259
+ self . index += 1 ;
260
+ Some ( & self . file_buffer [ self . index - self . buffer . len ( ) - 1 ] )
222
261
} else {
223
- let length = self . file_vec . len ( ) / std:: mem:: size_of :: < T > ( ) ;
224
- let ts =
225
- unsafe { std:: slice:: from_raw_parts ( self . file_vec . as_ptr ( ) as * const T , length) } ;
226
- if self . index - self . buffer . len ( ) < ts. len ( ) {
227
- self . index += 1 ;
228
- Some ( & ts[ self . index - self . buffer . len ( ) - 1 ] )
229
- } else {
230
- None
231
- }
262
+ None
232
263
}
233
264
}
234
265
}
@@ -256,8 +287,14 @@ impl<T: Hash + Eq + 'static> Collector<T> {
256
287
Ok ( ( ) )
257
288
}
258
289
259
- pub fn try_iter ( & self ) -> std:: io:: Result < impl Iterator < Item = & Entry < T > > > {
260
- Ok ( self . map . iter ( ) . chain ( self . temp_array . try_iter ( ) ?) )
290
+ pub fn try_iter < ' lt > (
291
+ & ' lt self ,
292
+ file_buffer_store : & ' lt mut Option < Box < [ ManuallyDrop < Entry < T > > ] > > ,
293
+ ) -> std:: io:: Result < impl Iterator < Item = & ' lt Entry < T > > > {
294
+ Ok ( self
295
+ . map
296
+ . iter ( )
297
+ . chain ( self . temp_array . try_iter ( file_buffer_store) ?) )
261
298
}
262
299
}
263
300
@@ -343,9 +380,13 @@ mod tests {
343
380
}
344
381
}
345
382
346
- collector. try_iter ( ) . unwrap ( ) . for_each ( |entry| {
347
- test_utils:: add_map ( & mut real_map, entry) ;
348
- } ) ;
383
+ let mut file_buffer_store = None ;
384
+ collector
385
+ . try_iter ( & mut file_buffer_store)
386
+ . unwrap ( )
387
+ . for_each ( |entry| {
388
+ test_utils:: add_map ( & mut real_map, entry) ;
389
+ } ) ;
349
390
350
391
for item in 0 ..( 1 << 12 ) * 4 {
351
392
let count = ( item % 4 ) as isize ;
0 commit comments