@@ -100,6 +100,13 @@ impl<K, V> LinkedHashMapEntry<K, V> {
100
100
}
101
101
}
102
102
103
+ unsafe fn drop_empty_entry_box < K , V > ( the_box : * mut LinkedHashMapEntry < K , V > ) {
104
+ // Prevent compiler from trying to drop the un-initialized key and values in the node.
105
+ let LinkedHashMapEntry { key, value, .. } = * Box :: from_raw ( the_box) ;
106
+ mem:: forget ( key) ;
107
+ mem:: forget ( value) ;
108
+ }
109
+
103
110
impl < K : Hash + Eq , V > LinkedHashMap < K , V > {
104
111
/// Creates a linked hash map.
105
112
pub fn new ( ) -> LinkedHashMap < K , V > { LinkedHashMap :: with_map ( HashMap :: new ( ) ) }
@@ -112,15 +119,10 @@ impl<K: Hash + Eq, V> LinkedHashMap<K, V> {
112
119
113
120
impl < K : Hash + Eq , V , S : HashState > LinkedHashMap < K , V , S > {
114
121
fn with_map ( map : HashMap < KeyRef < K > , Box < LinkedHashMapEntry < K , V > > , S > ) -> LinkedHashMap < K , V , S > {
115
- let map = LinkedHashMap {
122
+ LinkedHashMap {
116
123
map : map,
117
- head : unsafe { Box :: into_raw ( Box :: new ( mem:: uninitialized ( ) ) ) } ,
118
- } ;
119
- unsafe {
120
- ( * map. head ) . next = map. head ;
121
- ( * map. head ) . prev = map. head ;
124
+ head : ptr:: null_mut ( ) ,
122
125
}
123
- return map;
124
126
}
125
127
126
128
/// Creates an empty linked hash map with the given initial hash state.
@@ -161,6 +163,14 @@ impl<K: Hash + Eq, V, S: HashState> LinkedHashMap<K, V, S> {
161
163
/// assert_eq!(map[&2], "b");
162
164
/// ```
163
165
pub fn insert ( & mut self , k : K , v : V ) -> Option < V > {
166
+ if self . head . is_null ( ) {
167
+ // allocate the guard node if not present
168
+ unsafe {
169
+ self . head = Box :: into_raw ( Box :: new ( mem:: uninitialized ( ) ) ) ;
170
+ ( * self . head ) . next = self . head ;
171
+ ( * self . head ) . prev = self . head ;
172
+ }
173
+ }
164
174
let ( node_ptr, node_opt, old_val) = match self . map . get_mut ( & KeyRef { k : & k} ) {
165
175
Some ( node) => {
166
176
let old_val = mem:: replace ( & mut node. value , v) ;
@@ -405,9 +415,12 @@ impl<K: Hash + Eq, V, S: HashState> LinkedHashMap<K, V, S> {
405
415
/// Clear the map of all key-value pairs.
406
416
pub fn clear ( & mut self ) {
407
417
self . map . clear ( ) ;
408
- unsafe {
409
- ( * self . head ) . prev = self . head ;
410
- ( * self . head ) . next = self . head ;
418
+ // update the guard node if present
419
+ if ! self . head . is_null ( ) {
420
+ unsafe {
421
+ ( * self . head ) . prev = self . head ;
422
+ ( * self . head ) . next = self . head ;
423
+ }
411
424
}
412
425
}
413
426
@@ -430,8 +443,13 @@ impl<K: Hash + Eq, V, S: HashState> LinkedHashMap<K, V, S> {
430
443
/// assert_eq!(None, iter.next());
431
444
/// ```
432
445
pub fn iter ( & self ) -> Iter < K , V > {
446
+ let head = if ! self . head . is_null ( ) {
447
+ unsafe { ( * self . head ) . prev }
448
+ } else {
449
+ ptr:: null_mut ( )
450
+ } ;
433
451
Iter {
434
- head : unsafe { ( * self . head ) . prev } ,
452
+ head : head,
435
453
tail : self . head ,
436
454
remaining : self . len ( ) ,
437
455
marker : marker:: PhantomData ,
@@ -459,8 +477,13 @@ impl<K: Hash + Eq, V, S: HashState> LinkedHashMap<K, V, S> {
459
477
/// assert_eq!(&17, map.get(&"a").unwrap());
460
478
/// ```
461
479
pub fn iter_mut ( & mut self ) -> IterMut < K , V > {
480
+ let head = if ! self . head . is_null ( ) {
481
+ unsafe { ( * self . head ) . prev }
482
+ } else {
483
+ ptr:: null_mut ( )
484
+ } ;
462
485
IterMut {
463
- head : unsafe { ( * self . head ) . prev } ,
486
+ head : head,
464
487
tail : self . head ,
465
488
remaining : self . len ( ) ,
466
489
marker : marker:: PhantomData ,
@@ -649,10 +672,9 @@ unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LinkedHashMap<K, V, S> {}
649
672
impl < K , V , S > Drop for LinkedHashMap < K , V , S > {
650
673
fn drop ( & mut self ) {
651
674
unsafe {
652
- // Prevent compiler from trying to drop the un-initialized field in the sigil node.
653
- let LinkedHashMapEntry { next : _, prev : _, key : k, value : v } = * Box :: from_raw ( self . head ) ;
654
- mem:: forget ( k) ;
655
- mem:: forget ( v) ;
675
+ if ! self . head . is_null ( ) {
676
+ drop_empty_entry_box ( self . head ) ;
677
+ }
656
678
}
657
679
}
658
680
}
0 commit comments