Skip to content

Commit e30a48c

Browse files
authored
Merge pull request #54 from dtolnay/ptr
HashMap<KeyRef<K>, *mut LinkedHashMapEntry<K, V>>
2 parents 08590c8 + e6a4fb0 commit e30a48c

File tree

1 file changed

+56
-41
lines changed

1 file changed

+56
-41
lines changed

src/lib.rs

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct LinkedHashMapEntry<K, V> {
6060

6161
/// A linked hash map.
6262
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>,
6464
head: *mut LinkedHashMapEntry<K, V>,
6565
free: *mut LinkedHashMapEntry<K, V>,
6666
}
@@ -124,6 +124,16 @@ impl<K: Hash + Eq, V> LinkedHashMap<K, V> {
124124
}
125125

126126
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+
127137
fn clear_free_list(&mut self) {
128138
unsafe {
129139
let mut free = self.free;
@@ -138,7 +148,7 @@ impl<K, V, S> LinkedHashMap<K, V, S> {
138148
}
139149

140150
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 {
142152
LinkedHashMap {
143153
map: map,
144154
head: ptr::null_mut(),
@@ -195,38 +205,36 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
195205
(*self.head).prev = self.head;
196206
}
197207
}
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}) {
199209
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))
203212
}
204213
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)))
207216
} else {
208217
// use a recycled box
209218
unsafe {
210219
let free = self.free;
211220
self.free = (*free).next;
212221
ptr::write(free, LinkedHashMapEntry::new(k, v));
213-
Box::from_raw(free)
222+
free
214223
}
215224
};
216-
let node_ptr: *mut LinkedHashMapEntry<K, V> = &mut *node;
217-
(node_ptr, Some(node), None)
225+
(node, None)
218226
}
219227
};
220-
match node_opt {
221-
None => {
228+
match old_val {
229+
Some(_) => {
222230
// Existing node, just update LRU position
223-
self.detach(node_ptr);
224-
self.attach(node_ptr);
231+
self.detach(node);
232+
self.attach(node);
225233
}
226-
Some(node) => {
227-
let keyref = unsafe { &(*node_ptr).key };
234+
None => {
235+
let keyref = unsafe { &(*node).key };
228236
self.map.insert(KeyRef{k: keyref}, node);
229-
self.attach(node_ptr);
237+
self.attach(node);
230238
}
231239
}
232240
old_val
@@ -254,7 +262,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
254262
/// assert_eq!(map.get(&2), Some(&"c"));
255263
/// ```
256264
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 })
258266
}
259267

260268
/// 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> {
272280
/// assert_eq!(map.get(&1), Some(&"c"));
273281
/// ```
274282
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 })
276284
}
277285

278286
/// 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> {
295303
/// assert_eq!((&2, &"b"), map.iter().rev().next().unwrap());
296304
/// ```
297305
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)) {
299307
None => (None, None),
300308
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))
303310
}
304311
};
305312
if let Some(node_ptr) = node_ptr_opt {
@@ -326,17 +333,15 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
326333
/// ```
327334
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Eq + Hash {
328335
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);
332338
unsafe {
333339
// 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)
340345
}
341346
})
342347
}
@@ -378,7 +383,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
378383
self.detach(lru);
379384
self.map
380385
.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+
})
382390
}
383391

384392
/// Gets the first entry.
@@ -398,8 +406,9 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
398406
return None
399407
}
400408
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) })
403412
}
404413

405414
/// Removes the last entry.
@@ -424,7 +433,10 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
424433
self.detach(mru);
425434
self.map
426435
.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+
})
428440
}
429441

430442
/// Gets the last entry.
@@ -444,8 +456,9 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
444456
return None
445457
}
446458
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) })
449462
}
450463

451464
/// 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> {
460473
// update the guard node if present
461474
if ! self.head.is_null() {
462475
unsafe {
476+
self.drop_entries();
463477
(*self.head).prev = self.head;
464478
(*self.head).next = self.head;
465479
}
@@ -725,12 +739,13 @@ unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LinkedHashMap<K, V, S> {}
725739

726740
impl<K, V, S> Drop for LinkedHashMap<K, V, S> {
727741
fn drop(&mut self) {
728-
unsafe {
729-
if ! self.head.is_null() {
742+
if !self.head.is_null() {
743+
unsafe {
744+
self.drop_entries();
730745
drop_empty_entry_box(self.head);
731746
}
732-
self.clear_free_list();
733747
}
748+
self.clear_free_list();
734749
}
735750
}
736751

0 commit comments

Comments
 (0)