@@ -47,10 +47,9 @@ impl<T> core::ops::Deref for Bucket<T> {
47
47
/// resizing. When you interact with this API, keep in mind that there may be two backing tables,
48
48
/// and a lookup may return a reference to _either_. Eventually, entries in the old table will be
49
49
/// reclaimed, which invalidates any references to them.
50
- #[ derive( Clone ) ]
51
50
pub struct RawTable < T > {
52
51
table : raw:: RawTable < T > ,
53
- leftovers : Option < OldTable < T > > ,
52
+ leftovers : Option < raw :: RawIntoIter < T > > ,
54
53
}
55
54
56
55
impl < T > RawTable < T > {
@@ -92,33 +91,16 @@ impl<T> RawTable<T> {
92
91
if item. in_main {
93
92
self . table . erase_no_drop ( item) ;
94
93
} else if let Some ( ref mut lo) = self . leftovers {
95
- lo. table . erase_no_drop ( item) ;
94
+ lo. erase_no_drop ( item) ;
96
95
97
- if lo. table . len ( ) == 0 {
96
+ if lo. len ( ) == 0 {
98
97
let _ = self . leftovers . take ( ) ;
99
- } else {
100
- // By changing the state of the table, we have invalidated the table iterator
101
- // we keep for what elements are left to move. So, we re-compute it.
102
- //
103
- // TODO: We should be able to "fix up" the iterator rather than replace it,
104
- // which would save us from iterating over the prefix of empty buckets we've
105
- // left in our wake from the moves so far.
106
- lo. items = lo. table . iter ( ) ;
107
98
}
108
99
} else {
109
100
unreachable ! ( "invalid bucket state" ) ;
110
101
}
111
102
}
112
103
113
- /// Marks all table buckets as empty without dropping their contents.
114
- #[ cfg_attr( feature = "inline-more" , inline) ]
115
- pub fn clear_no_drop ( & mut self ) {
116
- self . table . clear_no_drop ( ) ;
117
- if let Some ( mut lo) = self . leftovers . take ( ) {
118
- lo. table . clear_no_drop ( ) ;
119
- }
120
- }
121
-
122
104
/// Removes all elements from the table without freeing the backing memory.
123
105
#[ cfg_attr( feature = "inline-more" , inline) ]
124
106
pub fn clear ( & mut self ) {
@@ -139,11 +121,11 @@ impl<T> RawTable<T> {
139
121
// are still leftovers.
140
122
if let Some ( ref lo) = self . leftovers {
141
123
// We need to move another lo.table.len() items.
142
- need += lo. table . len ( ) ;
124
+ need += lo. len ( ) ;
143
125
// We move R items on each insert.
144
126
// That means we need to accomodate another
145
127
// lo.table.len() / R (rounded up) inserts to move them all.
146
- need += ( lo. table . len ( ) + R - 1 ) / R ;
128
+ need += ( lo. len ( ) + R - 1 ) / R ;
147
129
}
148
130
let min_size = usize:: max ( need, min_size) ;
149
131
self . table . shrink_to ( min_size, hasher) ;
@@ -155,7 +137,7 @@ impl<T> RawTable<T> {
155
137
/// While we try to make this incremental where possible, it may require all-at-once resizing.
156
138
#[ cfg_attr( feature = "inline-more" , inline) ]
157
139
pub fn reserve ( & mut self , additional : usize , hasher : impl Fn ( & T ) -> u64 ) {
158
- let need = self . leftovers . as_ref ( ) . map_or ( 0 , |t| t. table . len ( ) ) + additional;
140
+ let need = self . leftovers . as_ref ( ) . map_or ( 0 , |t| t. len ( ) ) + additional;
159
141
if self . table . capacity ( ) - self . table . len ( ) > need {
160
142
// We can accommodate the additional items without resizing, so all is well.
161
143
if cfg ! ( debug_assertions) {
@@ -198,7 +180,7 @@ impl<T> RawTable<T> {
198
180
additional : usize ,
199
181
hasher : impl Fn ( & T ) -> u64 ,
200
182
) -> Result < ( ) , TryReserveError > {
201
- let need = self . leftovers . as_ref ( ) . map_or ( 0 , |t| t. table . len ( ) ) + additional;
183
+ let need = self . leftovers . as_ref ( ) . map_or ( 0 , |t| t. len ( ) ) + additional;
202
184
if self . table . capacity ( ) - self . table . len ( ) > need {
203
185
// we can accommodate the additional items without resizing, so all good
204
186
if cfg ! ( debug_assertions) {
@@ -273,8 +255,8 @@ impl<T> RawTable<T> {
273
255
} ) ;
274
256
}
275
257
276
- if let Some ( OldTable { ref table , .. } ) = self . leftovers {
277
- table . find ( hash, eq) . map ( |bucket| Bucket {
258
+ if let Some ( ref iter ) = self . leftovers {
259
+ iter . find ( hash, eq) . map ( |bucket| Bucket {
278
260
bucket,
279
261
in_main : false ,
280
262
} )
@@ -295,7 +277,7 @@ impl<T> RawTable<T> {
295
277
/// Returns the number of elements in the table.
296
278
#[ cfg_attr( feature = "inline-more" , inline) ]
297
279
pub fn len ( & self ) -> usize {
298
- self . table . len ( ) + self . leftovers . as_ref ( ) . map_or ( 0 , |t| t. table . len ( ) )
280
+ self . table . len ( ) + self . leftovers . as_ref ( ) . map_or ( 0 , |t| t. len ( ) )
299
281
}
300
282
301
283
/// Returns the number of buckets in the table.
@@ -312,7 +294,7 @@ impl<T> RawTable<T> {
312
294
pub unsafe fn iter ( & self ) -> RawIter < T > {
313
295
RawIter {
314
296
table : self . table . iter ( ) ,
315
- leftovers : self . leftovers . as_ref ( ) . map ( |lo| lo. items . clone ( ) ) ,
297
+ leftovers : self . leftovers . as_ref ( ) . map ( |lo| lo. iter ( ) ) ,
316
298
}
317
299
}
318
300
}
@@ -378,11 +360,7 @@ impl<T> RawTable<T> {
378
360
} ;
379
361
let old_table = mem:: replace ( & mut self . table , new_table) ;
380
362
if old_table. len ( ) != 0 {
381
- let old_table_items = unsafe { old_table. iter ( ) } ;
382
- self . leftovers = Some ( OldTable {
383
- table : old_table,
384
- items : old_table_items,
385
- } ) ;
363
+ self . leftovers = Some ( old_table. into_iter ( ) ) ;
386
364
}
387
365
Ok ( ( ) )
388
366
}
@@ -398,15 +376,13 @@ impl<T> RawTable<T> {
398
376
// NOTE: Calling next here could be expensive, as the iter needs to search for the
399
377
// next non-empty bucket. as the map grows in size, that search time will increase
400
378
// linearly.
401
- while let Some ( e ) = lo. items . next ( ) {
379
+ while let Some ( value ) = lo. next ( ) {
402
380
// We need to remove the item in this bucket from the old map
403
381
// to the resized map, without shrinking the old map.
404
- let value = unsafe { e. read ( ) } ;
405
382
let hash = hasher ( & value) ;
406
383
self . table . insert ( hash, value, & hasher) ;
407
384
}
408
385
// The resize is finally fully complete.
409
- lo. table . clear_no_drop ( ) ;
410
386
let _ = self . leftovers . take ( ) ;
411
387
}
412
388
}
@@ -423,14 +399,9 @@ impl<T> RawTable<T> {
423
399
// NOTE: Calling next here could be expensive, as the iter needs to search for the
424
400
// next non-empty bucket. as the map grows in size, that search time will increase
425
401
// linearly.
426
- if let Some ( e ) = lo. items . next ( ) {
402
+ if let Some ( value ) = lo. next ( ) {
427
403
// We need to remove the item in this bucket from the old map
428
404
// to the resized map, without shrinking the old map.
429
- let value = unsafe {
430
- let v = e. read ( ) ;
431
- lo. table . erase_no_drop ( & e) ;
432
- v
433
- } ;
434
405
let hash = hasher ( & value) ;
435
406
self . table . insert ( hash, value, & hasher) ;
436
407
} else {
@@ -457,8 +428,8 @@ impl<T> RawTable<T> {
457
428
}
458
429
459
430
#[ cfg( any( test, feature = "rayon" ) ) ]
460
- pub ( crate ) fn leftovers ( & self ) -> Option < & raw:: RawTable < T > > {
461
- self . leftovers . as_ref ( ) . map ( |lo| & lo . table )
431
+ pub ( crate ) fn leftovers ( & self ) -> Option < & raw:: RawIntoIter < T > > {
432
+ self . leftovers . as_ref ( )
462
433
}
463
434
}
464
435
@@ -470,35 +441,11 @@ impl<T> IntoIterator for RawTable<T> {
470
441
fn into_iter ( self ) -> RawIntoIter < T > {
471
442
RawIntoIter {
472
443
table : self . table . into_iter ( ) ,
473
- leftovers : self . leftovers . map ( |lo| {
474
- // TODO: make this re-use knowledge of progress from lo.items
475
- lo. table . into_iter ( )
476
- } ) ,
444
+ leftovers : self . leftovers ,
477
445
}
478
446
}
479
447
}
480
448
481
- struct OldTable < T > {
482
- table : raw:: RawTable < T > ,
483
-
484
- // We cache an iterator over the old table's buckets so we don't need to do a linear search
485
- // across buckets we know are empty each time we want to move more items.
486
- items : raw:: RawIter < T > ,
487
- }
488
-
489
- impl < T : Clone > Clone for OldTable < T > {
490
- fn clone ( & self ) -> OldTable < T > {
491
- let table = self . table . clone ( ) ;
492
- let items = unsafe { table. iter ( ) } ;
493
- OldTable { table, items }
494
- }
495
-
496
- fn clone_from ( & mut self , source : & Self ) {
497
- self . table . clone_from ( & source. table ) ;
498
- self . items = unsafe { self . table . iter ( ) } ;
499
- }
500
- }
501
-
502
449
/// Iterator which returns a raw pointer to every full bucket in the table.
503
450
pub struct RawIter < T > {
504
451
table : raw:: RawIter < T > ,
0 commit comments