diff options
| -rw-r--r-- | src/libcollections/lru_cache.rs | 63 |
1 files changed, 21 insertions, 42 deletions
diff --git a/src/libcollections/lru_cache.rs b/src/libcollections/lru_cache.rs index ef49ada322a..0b7199661f8 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: *K } struct LruEntry<K, V> { - key: Option<K>, - value: Option<V>, next: *mut LruEntry<K, V>, prev: *mut LruEntry<K, V>, + key: K, + value: V, } /// An LRU Cache. @@ -76,19 +77,10 @@ impl<K: Eq> Eq for KeyRef<K> { impl<K: TotalEq> TotalEq for KeyRef<K> {} impl<K, V> LruEntry<K, V> { - fn new() -> LruEntry<K, V> { + fn new(k: K, v: V) -> LruEntry<K, V> { LruEntry { - key: None, - value: None, - next: ptr::mut_null(), - prev: ptr::mut_null(), - } - } - - fn with_key_value(k: K, v: V) -> LruEntry<K, V> { - LruEntry { - key: Some(k), - value: Some(v), + key: k, + value: v, next: ptr::mut_null(), prev: ptr::mut_null(), } @@ -101,7 +93,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> { let cache = LruCache { map: HashMap::new(), max_size: capacity, - head: unsafe{ cast::transmute(~LruEntry::<K, V>::new()) }, + head: unsafe{ cast::transmute(~mem::uninit::<LruEntry<K, V>>()) }, }; unsafe { (*cache.head).next = cache.head; @@ -114,23 +106,24 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> { 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<K, V> = &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<K, V> = &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<K: Hash + TotalEq, V> LruCache<K, V> { None => (None, None), Some(node) => { let node_ptr: *mut LruEntry<K, V> = &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<K: Hash + TotalEq, V> LruCache<K, V> { pub fn pop(&mut self, k: &K) -> Option<V> { 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<K: Hash + TotalEq, V> LruCache<K, V> { 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<A: fmt::Show + Hash + TotalEq, B: fmt::Show> fmt::Show for LruCache<A, B> { 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<K: Hash + TotalEq, V> Mutable for LruCache<K, V> { impl<K, V> Drop for LruCache<K, V> { fn drop(&mut self) { unsafe { - let _: ~LruEntry<K, V> = cast::transmute(self.head); + let node: ~LruEntry<K, V> = 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); } } } |
