diff --git a/src/libcollections/lru_cache.rs b/src/libcollections/lru_cache.rs index ef49ada322a4..0b7199661f8e 100644 --- a/src/libcollections/lru_cache.rs +++ b/src/libcollections/lru_cache.rs @@ -41,6 +41,7 @@ use std::cast; use std::container::Container; use std::hash::Hash; use std::fmt; +use std::mem; use std::ptr; use HashMap; @@ -48,10 +49,10 @@ use HashMap; struct KeyRef { k: *K } struct LruEntry { - key: Option, - value: Option, next: *mut LruEntry, prev: *mut LruEntry, + key: K, + value: V, } /// An LRU Cache. @@ -76,19 +77,10 @@ impl Eq for KeyRef { impl TotalEq for KeyRef {} impl LruEntry { - fn new() -> LruEntry { + fn new(k: K, v: V) -> LruEntry { LruEntry { - key: None, - value: None, - next: ptr::mut_null(), - prev: ptr::mut_null(), - } - } - - fn with_key_value(k: K, v: V) -> LruEntry { - LruEntry { - key: Some(k), - value: Some(v), + key: k, + value: v, next: ptr::mut_null(), prev: ptr::mut_null(), } @@ -101,7 +93,7 @@ impl LruCache { let cache = LruCache { map: HashMap::new(), max_size: capacity, - head: unsafe{ cast::transmute(~LruEntry::::new()) }, + head: unsafe{ cast::transmute(~mem::uninit::>()) }, }; unsafe { (*cache.head).next = cache.head; @@ -114,23 +106,24 @@ impl LruCache { pub fn put(&mut self, k: K, v: V) { let (node_ptr, node_opt) = match self.map.find_mut(&KeyRef{k: &k}) { Some(node) => { - node.value = Some(v); + node.value = v; let node_ptr: *mut LruEntry = &mut **node; (node_ptr, None) } None => { - let mut node = ~LruEntry::with_key_value(k, v); + let mut node = ~LruEntry::new(k, v); let node_ptr: *mut LruEntry = &mut *node; (node_ptr, Some(node)) } }; match node_opt { None => { + // Existing node, just update LRU position self.detach(node_ptr); self.attach(node_ptr); } Some(node) => { - let keyref = unsafe { (*node_ptr).key.as_ref().unwrap() }; + let keyref = unsafe { &(*node_ptr).key }; self.map.swap(KeyRef{k: keyref}, node); self.attach(node_ptr); if self.len() > self.capacity() { @@ -146,12 +139,7 @@ impl LruCache { None => (None, None), Some(node) => { let node_ptr: *mut LruEntry = &mut **node; - unsafe { - match (*node_ptr).value { - None => (None, None), - Some(ref value) => (Some(value), Some(node_ptr)) - } - } + (Some(unsafe { &(*node_ptr).value }), Some(node_ptr)) } }; match node_ptr_opt { @@ -168,7 +156,7 @@ impl LruCache { pub fn pop(&mut self, k: &K) -> Option { match self.map.pop(&KeyRef{k: k}) { None => None, - Some(lru_entry) => lru_entry.value + Some(lru_entry) => Some(lru_entry.value) } } @@ -191,12 +179,7 @@ impl LruCache { if self.len() > 0 { let lru = unsafe { (*self.head).prev }; self.detach(lru); - unsafe { - match (*lru).key { - None => (), - Some(ref k) => { self.map.pop(&KeyRef{k: k}); } - } - } + self.map.pop(&KeyRef{k: unsafe { &(*lru).key }}); } } @@ -229,19 +212,11 @@ impl fmt::Show for LruCache { if i > 0 { try!(write!(f.buf, ", ")) } unsafe { cur = (*cur).next; - match (*cur).key { - // should never print nil - None => try!(write!(f.buf, "nil")), - Some(ref k) => try!(write!(f.buf, "{}", *k)), - } + try!(write!(f.buf, "{}", (*cur).key)); } try!(write!(f.buf, ": ")); unsafe { - match (*cur).value { - // should never print nil - None => try!(write!(f.buf, "nil")), - Some(ref value) => try!(write!(f.buf, "{}", *value)), - } + try!(write!(f.buf, "{}", (*cur).value)); } } write!(f.buf, r"\}") @@ -266,7 +241,11 @@ impl Mutable for LruCache { impl Drop for LruCache { fn drop(&mut self) { unsafe { - let _: ~LruEntry = cast::transmute(self.head); + let node: ~LruEntry = cast::transmute(self.head); + // Prevent compiler from trying to drop the un-initialized field in the sigil node. + let ~LruEntry { key: k, value: v, .. } = node; + cast::forget(k); + cast::forget(v); } } }