@@ -41,17 +41,18 @@ use std::cast;
4141use std:: container:: Container ;
4242use std:: hash:: Hash ;
4343use std:: fmt;
44+ use std:: mem;
4445use std:: ptr;
4546
4647use HashMap ;
4748
4849struct KeyRef < K > { k : * K }
4950
5051struct LruEntry < K , V > {
51- key : Option < K > ,
52- value : Option < V > ,
5352 next : * mut LruEntry < K , V > ,
5453 prev : * mut LruEntry < K , V > ,
54+ key : K ,
55+ value : V ,
5556}
5657
5758/// An LRU Cache.
@@ -76,19 +77,10 @@ impl<K: Eq> Eq for KeyRef<K> {
7677impl < K : TotalEq > TotalEq for KeyRef < K > { }
7778
7879impl < K , V > LruEntry < K , V > {
79- fn new ( ) -> LruEntry < K , V > {
80+ fn new ( k : K , v : V ) -> LruEntry < K , V > {
8081 LruEntry {
81- key : None ,
82- value : None ,
83- next : ptr:: mut_null ( ) ,
84- prev : ptr:: mut_null ( ) ,
85- }
86- }
87-
88- fn with_key_value ( k : K , v : V ) -> LruEntry < K , V > {
89- LruEntry {
90- key : Some ( k) ,
91- value : Some ( v) ,
82+ key : k,
83+ value : v,
9284 next : ptr:: mut_null ( ) ,
9385 prev : ptr:: mut_null ( ) ,
9486 }
@@ -101,7 +93,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
10193 let cache = LruCache {
10294 map : HashMap :: new ( ) ,
10395 max_size : capacity,
104- head : unsafe { cast:: transmute ( ~LruEntry :: < K , V > :: new ( ) ) } ,
96+ head : unsafe { cast:: transmute ( ~mem :: uninit :: < LruEntry < K , V > > ( ) ) } ,
10597 } ;
10698 unsafe {
10799 ( * cache. head ) . next = cache. head ;
@@ -114,23 +106,24 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
114106 pub fn put ( & mut self , k : K , v : V ) {
115107 let ( node_ptr, node_opt) = match self . map . find_mut ( & KeyRef { k : & k} ) {
116108 Some ( node) => {
117- node. value = Some ( v ) ;
109+ node. value = v ;
118110 let node_ptr: * mut LruEntry < K , V > = & mut * * node;
119111 ( node_ptr, None )
120112 }
121113 None => {
122- let mut node = ~LruEntry :: with_key_value ( k, v) ;
114+ let mut node = ~LruEntry :: new ( k, v) ;
123115 let node_ptr: * mut LruEntry < K , V > = & mut * node;
124116 ( node_ptr, Some ( node) )
125117 }
126118 } ;
127119 match node_opt {
128120 None => {
121+ // Existing node, just update LRU position
129122 self . detach ( node_ptr) ;
130123 self . attach ( node_ptr) ;
131124 }
132125 Some ( node) => {
133- let keyref = unsafe { ( * node_ptr) . key . as_ref ( ) . unwrap ( ) } ;
126+ let keyref = unsafe { & ( * node_ptr) . key } ;
134127 self . map . swap ( KeyRef { k : keyref} , node) ;
135128 self . attach ( node_ptr) ;
136129 if self . len ( ) > self . capacity ( ) {
@@ -146,12 +139,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
146139 None => ( None , None ) ,
147140 Some ( node) => {
148141 let node_ptr: * mut LruEntry < K , V > = & mut * * node;
149- unsafe {
150- match ( * node_ptr) . value {
151- None => ( None , None ) ,
152- Some ( ref value) => ( Some ( value) , Some ( node_ptr) )
153- }
154- }
142+ ( Some ( unsafe { & ( * node_ptr) . value } ) , Some ( node_ptr) )
155143 }
156144 } ;
157145 match node_ptr_opt {
@@ -168,7 +156,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
168156 pub fn pop ( & mut self , k : & K ) -> Option < V > {
169157 match self . map . pop ( & KeyRef { k : k} ) {
170158 None => None ,
171- Some ( lru_entry) => lru_entry. value
159+ Some ( lru_entry) => Some ( lru_entry. value )
172160 }
173161 }
174162
@@ -191,12 +179,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
191179 if self . len ( ) > 0 {
192180 let lru = unsafe { ( * self . head ) . prev } ;
193181 self . detach ( lru) ;
194- unsafe {
195- match ( * lru) . key {
196- None => ( ) ,
197- Some ( ref k) => { self . map . pop ( & KeyRef { k : k} ) ; }
198- }
199- }
182+ self . map . pop ( & KeyRef { k : unsafe { & ( * lru) . key } } ) ;
200183 }
201184 }
202185
@@ -229,19 +212,11 @@ impl<A: fmt::Show + Hash + TotalEq, B: fmt::Show> fmt::Show for LruCache<A, B> {
229212 if i > 0 { try!( write ! ( f. buf, ", " ) ) }
230213 unsafe {
231214 cur = ( * cur) . next ;
232- match ( * cur) . key {
233- // should never print nil
234- None => try!( write ! ( f. buf, "nil" ) ) ,
235- Some ( ref k) => try!( write ! ( f. buf, "{}" , * k) ) ,
236- }
215+ try!( write ! ( f. buf, "{}" , ( * cur) . key) ) ;
237216 }
238217 try!( write ! ( f. buf, ": " ) ) ;
239218 unsafe {
240- match ( * cur) . value {
241- // should never print nil
242- None => try!( write ! ( f. buf, "nil" ) ) ,
243- Some ( ref value) => try!( write ! ( f. buf, "{}" , * value) ) ,
244- }
219+ try!( write ! ( f. buf, "{}" , ( * cur) . value) ) ;
245220 }
246221 }
247222 write ! ( f. buf, r"\}" )
@@ -266,7 +241,11 @@ impl<K: Hash + TotalEq, V> Mutable for LruCache<K, V> {
266241impl < K , V > Drop for LruCache < K , V > {
267242 fn drop ( & mut self ) {
268243 unsafe {
269- let _: ~LruEntry < K , V > = cast:: transmute ( self . head ) ;
244+ let node: ~LruEntry < K , V > = cast:: transmute ( self . head ) ;
245+ // Prevent compiler from trying to drop the un-initialized field in the sigil node.
246+ let ~LruEntry { key : k, value : v, .. } = node;
247+ cast:: forget ( k) ;
248+ cast:: forget ( v) ;
270249 }
271250 }
272251}
0 commit comments