@@ -57,7 +57,7 @@ struct LinkedHashMapEntry<K, V> {
57
57
58
58
/// A linked hash map.
59
59
pub struct LinkedHashMap < K , V , S = hash_map:: RandomState > {
60
- map : HashMap < KeyRef < K > , Box < LinkedHashMapEntry < K , V > > , S > ,
60
+ map : HashMap < KeyRef < K > , * mut LinkedHashMapEntry < K , V > , S > ,
61
61
head : * mut LinkedHashMapEntry < K , V > ,
62
62
free : * mut LinkedHashMapEntry < K , V > ,
63
63
}
@@ -121,6 +121,16 @@ impl<K: Hash + Eq, V> LinkedHashMap<K, V> {
121
121
}
122
122
123
123
impl < K , V , S > LinkedHashMap < K , V , S > {
124
+ // Caller must check `!self.head.is_null()`
125
+ unsafe fn drop_entries ( & mut self ) {
126
+ let mut cur = ( * self . head ) . next ;
127
+ while cur != self . head {
128
+ let next = ( * cur) . next ;
129
+ Box :: from_raw ( cur) ;
130
+ cur = next;
131
+ }
132
+ }
133
+
124
134
fn clear_free_list ( & mut self ) {
125
135
unsafe {
126
136
let mut free = self . free ;
@@ -135,7 +145,7 @@ impl<K, V, S> LinkedHashMap<K, V, S> {
135
145
}
136
146
137
147
impl < K : Hash + Eq , V , S : BuildHasher > LinkedHashMap < K , V , S > {
138
- fn with_map ( map : HashMap < KeyRef < K > , Box < LinkedHashMapEntry < K , V > > , S > ) -> Self {
148
+ fn with_map ( map : HashMap < KeyRef < K > , * mut LinkedHashMapEntry < K , V > , S > ) -> Self {
139
149
LinkedHashMap {
140
150
map : map,
141
151
head : ptr:: null_mut ( ) ,
@@ -192,38 +202,36 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
192
202
( * self . head ) . prev = self . head ;
193
203
}
194
204
}
195
- let ( node_ptr , node_opt , old_val) = match self . map . get_mut ( & KeyRef { k : & k} ) {
205
+ let ( node , old_val) = match self . map . get ( & KeyRef { k : & k} ) {
196
206
Some ( node) => {
197
- let old_val = mem:: replace ( & mut node. value , v) ;
198
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * * node;
199
- ( node_ptr, None , Some ( old_val) )
207
+ let old_val = unsafe { ptr:: replace ( & mut ( * * node) . value , v) } ;
208
+ ( * node, Some ( old_val) )
200
209
}
201
210
None => {
202
- let mut node = if self . free . is_null ( ) {
203
- Box :: new ( LinkedHashMapEntry :: new ( k, v) )
211
+ let node = if self . free . is_null ( ) {
212
+ Box :: into_raw ( Box :: new ( LinkedHashMapEntry :: new ( k, v) ) )
204
213
} else {
205
214
// use a recycled box
206
215
unsafe {
207
216
let free = self . free ;
208
217
self . free = ( * free) . next ;
209
218
ptr:: write ( free, LinkedHashMapEntry :: new ( k, v) ) ;
210
- Box :: from_raw ( free)
219
+ free
211
220
}
212
221
} ;
213
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * node;
214
- ( node_ptr, Some ( node) , None )
222
+ ( node, None )
215
223
}
216
224
} ;
217
- match node_opt {
218
- None => {
225
+ match old_val {
226
+ Some ( _ ) => {
219
227
// Existing node, just update LRU position
220
- self . detach ( node_ptr ) ;
221
- self . attach ( node_ptr ) ;
228
+ self . detach ( node ) ;
229
+ self . attach ( node ) ;
222
230
}
223
- Some ( node ) => {
224
- let keyref = unsafe { & ( * node_ptr ) . key } ;
231
+ None => {
232
+ let keyref = unsafe { & ( * node ) . key } ;
225
233
self . map . insert ( KeyRef { k : keyref} , node) ;
226
- self . attach ( node_ptr ) ;
234
+ self . attach ( node ) ;
227
235
}
228
236
}
229
237
old_val
@@ -251,7 +259,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
251
259
/// assert_eq!(map.get(&2), Some(&"c"));
252
260
/// ```
253
261
pub fn get < Q : ?Sized > ( & self , k : & Q ) -> Option < & V > where K : Borrow < Q > , Q : Eq + Hash {
254
- self . map . get ( Qey :: from_ref ( k) ) . map ( |e| & e . value )
262
+ self . map . get ( Qey :: from_ref ( k) ) . map ( |e| unsafe { & ( * * e ) . value } )
255
263
}
256
264
257
265
/// Returns the mutable reference corresponding to the key in the map.
@@ -269,7 +277,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
269
277
/// assert_eq!(map.get(&1), Some(&"c"));
270
278
/// ```
271
279
pub fn get_mut < Q : ?Sized > ( & mut self , k : & Q ) -> Option < & mut V > where K : Borrow < Q > , Q : Eq + Hash {
272
- self . map . get_mut ( Qey :: from_ref ( k) ) . map ( |e| & mut e . value )
280
+ self . map . get ( Qey :: from_ref ( k) ) . map ( |e| unsafe { & mut ( * * e ) . value } )
273
281
}
274
282
275
283
/// Returns the value corresponding to the key in the map.
@@ -292,11 +300,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
292
300
/// assert_eq!((&2, &"b"), map.iter().rev().next().unwrap());
293
301
/// ```
294
302
pub fn get_refresh < Q : ?Sized > ( & mut self , k : & Q ) -> Option < & mut V > where K : Borrow < Q > , Q : Eq + Hash {
295
- let ( value, node_ptr_opt) = match self . map . get_mut ( Qey :: from_ref ( k) ) {
303
+ let ( value, node_ptr_opt) = match self . map . get ( Qey :: from_ref ( k) ) {
296
304
None => ( None , None ) ,
297
305
Some ( node) => {
298
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * * node;
299
- ( Some ( unsafe { & mut ( * node_ptr) . value } ) , Some ( node_ptr) )
306
+ ( Some ( unsafe { & mut ( * * node) . value } ) , Some ( * node) )
300
307
}
301
308
} ;
302
309
if let Some ( node_ptr) = node_ptr_opt {
@@ -323,17 +330,15 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
323
330
/// ```
324
331
pub fn remove < Q : ?Sized > ( & mut self , k : & Q ) -> Option < V > where K : Borrow < Q > , Q : Eq + Hash {
325
332
let removed = self . map . remove ( Qey :: from_ref ( k) ) ;
326
- removed. map ( |mut node| {
327
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * node;
328
- self . detach ( node_ptr) ;
333
+ removed. map ( |node| {
334
+ self . detach ( node) ;
329
335
unsafe {
330
336
// add to free list
331
- ( * node_ptr) . next = self . free ;
332
- self . free = node_ptr;
333
- // forget the box but drop the key and return the value
334
- mem:: forget ( node) ;
335
- drop ( ptr:: read ( & ( * node_ptr) . key ) ) ;
336
- ptr:: read ( & ( * node_ptr) . value )
337
+ ( * node) . next = self . free ;
338
+ self . free = node;
339
+ // drop the key and return the value
340
+ drop ( ptr:: read ( & ( * node) . key ) ) ;
341
+ ptr:: read ( & ( * node) . value )
337
342
}
338
343
} )
339
344
}
@@ -373,7 +378,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
373
378
self . detach ( lru) ;
374
379
return self . map
375
380
. remove ( & KeyRef { k : unsafe { & ( * lru) . key } } )
376
- . map ( |e| { let e = * e; ( e. key , e. value ) } )
381
+ . map ( |e| {
382
+ let e = * unsafe { Box :: from_raw ( e) } ;
383
+ ( e. key , e. value )
384
+ } )
377
385
}
378
386
None
379
387
}
@@ -394,7 +402,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
394
402
if self . len ( ) > 0 {
395
403
let lru = unsafe { ( * self . head ) . prev } ;
396
404
return self . map . get ( & KeyRef { k : unsafe { & ( * lru) . key } } )
397
- . map ( |e| ( & e . key , & e . value ) )
405
+ . map ( |e| unsafe { ( & ( * * e ) . key , & ( * * e ) . value ) } )
398
406
}
399
407
None
400
408
}
@@ -419,7 +427,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
419
427
self . detach ( mru) ;
420
428
return self . map
421
429
. remove ( & KeyRef { k : unsafe { & ( * mru) . key } } )
422
- . map ( |e| { let e = * e; ( e. key , e. value ) } )
430
+ . map ( |e| {
431
+ let e = * unsafe { Box :: from_raw ( e) } ;
432
+ ( e. key , e. value )
433
+ } )
423
434
}
424
435
None
425
436
}
@@ -440,7 +451,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
440
451
if self . len ( ) > 0 {
441
452
let mru = unsafe { ( * self . head ) . next } ;
442
453
return self . map . get ( & KeyRef { k : unsafe { & ( * mru) . key } } )
443
- . map ( |e| ( & e . key , & e . value ) )
454
+ . map ( |e| unsafe { ( & ( * * e ) . key , & ( * * e ) . value ) } )
444
455
}
445
456
None
446
457
}
@@ -457,6 +468,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
457
468
// update the guard node if present
458
469
if ! self . head . is_null ( ) {
459
470
unsafe {
471
+ self . drop_entries ( ) ;
460
472
( * self . head ) . prev = self . head ;
461
473
( * self . head ) . next = self . head ;
462
474
}
@@ -720,12 +732,13 @@ unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LinkedHashMap<K, V, S> {}
720
732
721
733
impl < K , V , S > Drop for LinkedHashMap < K , V , S > {
722
734
fn drop ( & mut self ) {
723
- unsafe {
724
- if ! self . head . is_null ( ) {
735
+ if !self . head . is_null ( ) {
736
+ unsafe {
737
+ self . drop_entries ( ) ;
725
738
drop_empty_entry_box ( self . head ) ;
726
739
}
727
- self . clear_free_list ( ) ;
728
740
}
741
+ self . clear_free_list ( ) ;
729
742
}
730
743
}
731
744
0 commit comments