@@ -60,7 +60,7 @@ struct LinkedHashMapEntry<K, V> {
60
60
61
61
/// A linked hash map.
62
62
pub struct LinkedHashMap < K , V , S = hash_map:: RandomState > {
63
- map : HashMap < KeyRef < K > , Box < LinkedHashMapEntry < K , V > > , S > ,
63
+ map : HashMap < KeyRef < K > , * mut LinkedHashMapEntry < K , V > , S > ,
64
64
head : * mut LinkedHashMapEntry < K , V > ,
65
65
free : * mut LinkedHashMapEntry < K , V > ,
66
66
}
@@ -124,6 +124,16 @@ impl<K: Hash + Eq, V> LinkedHashMap<K, V> {
124
124
}
125
125
126
126
impl < K , V , S > LinkedHashMap < K , V , S > {
127
+ // Caller must check `!self.head.is_null()`
128
+ unsafe fn drop_entries ( & mut self ) {
129
+ let mut cur = ( * self . head ) . next ;
130
+ while cur != self . head {
131
+ let next = ( * cur) . next ;
132
+ Box :: from_raw ( cur) ;
133
+ cur = next;
134
+ }
135
+ }
136
+
127
137
fn clear_free_list ( & mut self ) {
128
138
unsafe {
129
139
let mut free = self . free ;
@@ -138,7 +148,7 @@ impl<K, V, S> LinkedHashMap<K, V, S> {
138
148
}
139
149
140
150
impl < K : Hash + Eq , V , S : BuildHasher > LinkedHashMap < K , V , S > {
141
- fn with_map ( map : HashMap < KeyRef < K > , Box < LinkedHashMapEntry < K , V > > , S > ) -> Self {
151
+ fn with_map ( map : HashMap < KeyRef < K > , * mut LinkedHashMapEntry < K , V > , S > ) -> Self {
142
152
LinkedHashMap {
143
153
map : map,
144
154
head : ptr:: null_mut ( ) ,
@@ -195,38 +205,36 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
195
205
( * self . head ) . prev = self . head ;
196
206
}
197
207
}
198
- let ( node_ptr , node_opt , old_val) = match self . map . get_mut ( & KeyRef { k : & k} ) {
208
+ let ( node , old_val) = match self . map . get ( & KeyRef { k : & k} ) {
199
209
Some ( node) => {
200
- let old_val = mem:: replace ( & mut node. value , v) ;
201
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * * node;
202
- ( node_ptr, None , Some ( old_val) )
210
+ let old_val = unsafe { ptr:: replace ( & mut ( * * node) . value , v) } ;
211
+ ( * node, Some ( old_val) )
203
212
}
204
213
None => {
205
- let mut node = if self . free . is_null ( ) {
206
- Box :: new ( LinkedHashMapEntry :: new ( k, v) )
214
+ let node = if self . free . is_null ( ) {
215
+ Box :: into_raw ( Box :: new ( LinkedHashMapEntry :: new ( k, v) ) )
207
216
} else {
208
217
// use a recycled box
209
218
unsafe {
210
219
let free = self . free ;
211
220
self . free = ( * free) . next ;
212
221
ptr:: write ( free, LinkedHashMapEntry :: new ( k, v) ) ;
213
- Box :: from_raw ( free)
222
+ free
214
223
}
215
224
} ;
216
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * node;
217
- ( node_ptr, Some ( node) , None )
225
+ ( node, None )
218
226
}
219
227
} ;
220
- match node_opt {
221
- None => {
228
+ match old_val {
229
+ Some ( _ ) => {
222
230
// Existing node, just update LRU position
223
- self . detach ( node_ptr ) ;
224
- self . attach ( node_ptr ) ;
231
+ self . detach ( node ) ;
232
+ self . attach ( node ) ;
225
233
}
226
- Some ( node ) => {
227
- let keyref = unsafe { & ( * node_ptr ) . key } ;
234
+ None => {
235
+ let keyref = unsafe { & ( * node ) . key } ;
228
236
self . map . insert ( KeyRef { k : keyref} , node) ;
229
- self . attach ( node_ptr ) ;
237
+ self . attach ( node ) ;
230
238
}
231
239
}
232
240
old_val
@@ -254,7 +262,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
254
262
/// assert_eq!(map.get(&2), Some(&"c"));
255
263
/// ```
256
264
pub fn get < Q : ?Sized > ( & self , k : & Q ) -> Option < & V > where K : Borrow < Q > , Q : Eq + Hash {
257
- self . map . get ( Qey :: from_ref ( k) ) . map ( |e| & e . value )
265
+ self . map . get ( Qey :: from_ref ( k) ) . map ( |e| unsafe { & ( * * e ) . value } )
258
266
}
259
267
260
268
/// Returns the mutable reference corresponding to the key in the map.
@@ -272,7 +280,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
272
280
/// assert_eq!(map.get(&1), Some(&"c"));
273
281
/// ```
274
282
pub fn get_mut < Q : ?Sized > ( & mut self , k : & Q ) -> Option < & mut V > where K : Borrow < Q > , Q : Eq + Hash {
275
- self . map . get_mut ( Qey :: from_ref ( k) ) . map ( |e| & mut e . value )
283
+ self . map . get ( Qey :: from_ref ( k) ) . map ( |e| unsafe { & mut ( * * e ) . value } )
276
284
}
277
285
278
286
/// Returns the value corresponding to the key in the map.
@@ -295,11 +303,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
295
303
/// assert_eq!((&2, &"b"), map.iter().rev().next().unwrap());
296
304
/// ```
297
305
pub fn get_refresh < Q : ?Sized > ( & mut self , k : & Q ) -> Option < & mut V > where K : Borrow < Q > , Q : Eq + Hash {
298
- let ( value, node_ptr_opt) = match self . map . get_mut ( Qey :: from_ref ( k) ) {
306
+ let ( value, node_ptr_opt) = match self . map . get ( Qey :: from_ref ( k) ) {
299
307
None => ( None , None ) ,
300
308
Some ( node) => {
301
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * * node;
302
- ( Some ( unsafe { & mut ( * node_ptr) . value } ) , Some ( node_ptr) )
309
+ ( Some ( unsafe { & mut ( * * node) . value } ) , Some ( * node) )
303
310
}
304
311
} ;
305
312
if let Some ( node_ptr) = node_ptr_opt {
@@ -326,17 +333,15 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
326
333
/// ```
327
334
pub fn remove < Q : ?Sized > ( & mut self , k : & Q ) -> Option < V > where K : Borrow < Q > , Q : Eq + Hash {
328
335
let removed = self . map . remove ( Qey :: from_ref ( k) ) ;
329
- removed. map ( |mut node| {
330
- let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * node;
331
- self . detach ( node_ptr) ;
336
+ removed. map ( |node| {
337
+ self . detach ( node) ;
332
338
unsafe {
333
339
// add to free list
334
- ( * node_ptr) . next = self . free ;
335
- self . free = node_ptr;
336
- // forget the box but drop the key and return the value
337
- mem:: forget ( node) ;
338
- drop ( ptr:: read ( & ( * node_ptr) . key ) ) ;
339
- ptr:: read ( & ( * node_ptr) . value )
340
+ ( * node) . next = self . free ;
341
+ self . free = node;
342
+ // drop the key and return the value
343
+ drop ( ptr:: read ( & ( * node) . key ) ) ;
344
+ ptr:: read ( & ( * node) . value )
340
345
}
341
346
} )
342
347
}
@@ -378,7 +383,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
378
383
self . detach ( lru) ;
379
384
self . map
380
385
. remove ( & KeyRef { k : unsafe { & ( * lru) . key } } )
381
- . map ( |e| { let e = * e; ( e. key , e. value ) } )
386
+ . map ( |e| {
387
+ let e = * unsafe { Box :: from_raw ( e) } ;
388
+ ( e. key , e. value )
389
+ } )
382
390
}
383
391
384
392
/// Gets the first entry.
@@ -398,8 +406,9 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
398
406
return None
399
407
}
400
408
let lru = unsafe { ( * self . head ) . prev } ;
401
- self . map . get ( & KeyRef { k : unsafe { & ( * lru) . key } } )
402
- . map ( |e| ( & e. key , & e. value ) )
409
+ self . map
410
+ . get ( & KeyRef { k : unsafe { & ( * lru) . key } } )
411
+ . map ( |e| unsafe { ( & ( * * e) . key , & ( * * e) . value ) } )
403
412
}
404
413
405
414
/// Removes the last entry.
@@ -424,7 +433,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
424
433
self . detach ( mru) ;
425
434
self . map
426
435
. remove ( & KeyRef { k : unsafe { & ( * mru) . key } } )
427
- . map ( |e| { let e = * e; ( e. key , e. value ) } )
436
+ . map ( |e| {
437
+ let e = * unsafe { Box :: from_raw ( e) } ;
438
+ ( e. key , e. value )
439
+ } )
428
440
}
429
441
430
442
/// Gets the last entry.
@@ -444,8 +456,9 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
444
456
return None
445
457
}
446
458
let mru = unsafe { ( * self . head ) . next } ;
447
- self . map . get ( & KeyRef { k : unsafe { & ( * mru) . key } } )
448
- . map ( |e| ( & e. key , & e. value ) )
459
+ self . map
460
+ . get ( & KeyRef { k : unsafe { & ( * mru) . key } } )
461
+ . map ( |e| unsafe { ( & ( * * e) . key , & ( * * e) . value ) } )
449
462
}
450
463
451
464
/// Returns the number of key-value pairs in the map.
@@ -460,6 +473,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
460
473
// update the guard node if present
461
474
if ! self . head . is_null ( ) {
462
475
unsafe {
476
+ self . drop_entries ( ) ;
463
477
( * self . head ) . prev = self . head ;
464
478
( * self . head ) . next = self . head ;
465
479
}
@@ -725,12 +739,13 @@ unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LinkedHashMap<K, V, S> {}
725
739
726
740
impl < K , V , S > Drop for LinkedHashMap < K , V , S > {
727
741
fn drop ( & mut self ) {
728
- unsafe {
729
- if ! self . head . is_null ( ) {
742
+ if !self . head . is_null ( ) {
743
+ unsafe {
744
+ self . drop_entries ( ) ;
730
745
drop_empty_entry_box ( self . head ) ;
731
746
}
732
- self . clear_free_list ( ) ;
733
747
}
748
+ self . clear_free_list ( ) ;
734
749
}
735
750
}
736
751
0 commit comments