@@ -41,17 +41,18 @@ use std::cast;
41
41
use std:: container:: Container ;
42
42
use std:: hash:: Hash ;
43
43
use std:: fmt;
44
+ use std:: mem;
44
45
use std:: ptr;
45
46
46
47
use HashMap ;
47
48
48
49
struct KeyRef < K > { k : * K }
49
50
50
51
struct LruEntry < K , V > {
51
- key : Option < K > ,
52
- value : Option < V > ,
53
52
next : * mut LruEntry < K , V > ,
54
53
prev : * mut LruEntry < K , V > ,
54
+ key : K ,
55
+ value : V ,
55
56
}
56
57
57
58
/// An LRU Cache.
@@ -76,19 +77,10 @@ impl<K: Eq> Eq for KeyRef<K> {
76
77
impl < K : TotalEq > TotalEq for KeyRef < K > { }
77
78
78
79
impl < K , V > LruEntry < K , V > {
79
- fn new ( ) -> LruEntry < K , V > {
80
+ fn new ( k : K , v : V ) -> LruEntry < K , V > {
80
81
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,
92
84
next : ptr:: mut_null ( ) ,
93
85
prev : ptr:: mut_null ( ) ,
94
86
}
@@ -101,7 +93,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
101
93
let cache = LruCache {
102
94
map : HashMap :: new ( ) ,
103
95
max_size : capacity,
104
- head : unsafe { cast:: transmute ( ~LruEntry :: < K , V > :: new ( ) ) } ,
96
+ head : unsafe { cast:: transmute ( ~mem :: uninit :: < LruEntry < K , V > > ( ) ) } ,
105
97
} ;
106
98
unsafe {
107
99
( * cache. head ) . next = cache. head ;
@@ -114,23 +106,24 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
114
106
pub fn put ( & mut self , k : K , v : V ) {
115
107
let ( node_ptr, node_opt) = match self . map . find_mut ( & KeyRef { k : & k} ) {
116
108
Some ( node) => {
117
- node. value = Some ( v ) ;
109
+ node. value = v ;
118
110
let node_ptr: * mut LruEntry < K , V > = & mut * * node;
119
111
( node_ptr, None )
120
112
}
121
113
None => {
122
- let mut node = ~LruEntry :: with_key_value ( k, v) ;
114
+ let mut node = ~LruEntry :: new ( k, v) ;
123
115
let node_ptr: * mut LruEntry < K , V > = & mut * node;
124
116
( node_ptr, Some ( node) )
125
117
}
126
118
} ;
127
119
match node_opt {
128
120
None => {
121
+ // Existing node, just update LRU position
129
122
self . detach ( node_ptr) ;
130
123
self . attach ( node_ptr) ;
131
124
}
132
125
Some ( node) => {
133
- let keyref = unsafe { ( * node_ptr) . key . as_ref ( ) . unwrap ( ) } ;
126
+ let keyref = unsafe { & ( * node_ptr) . key } ;
134
127
self . map . swap ( KeyRef { k : keyref} , node) ;
135
128
self . attach ( node_ptr) ;
136
129
if self . len ( ) > self . capacity ( ) {
@@ -146,12 +139,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
146
139
None => ( None , None ) ,
147
140
Some ( node) => {
148
141
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) )
155
143
}
156
144
} ;
157
145
match node_ptr_opt {
@@ -168,7 +156,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
168
156
pub fn pop ( & mut self , k : & K ) -> Option < V > {
169
157
match self . map . pop ( & KeyRef { k : k} ) {
170
158
None => None ,
171
- Some ( lru_entry) => lru_entry. value
159
+ Some ( lru_entry) => Some ( lru_entry. value )
172
160
}
173
161
}
174
162
@@ -191,12 +179,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
191
179
if self . len ( ) > 0 {
192
180
let lru = unsafe { ( * self . head ) . prev } ;
193
181
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 } } ) ;
200
183
}
201
184
}
202
185
@@ -229,19 +212,11 @@ impl<A: fmt::Show + Hash + TotalEq, B: fmt::Show> fmt::Show for LruCache<A, B> {
229
212
if i > 0 { try!( write ! ( f. buf, ", " ) ) }
230
213
unsafe {
231
214
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) ) ;
237
216
}
238
217
try!( write ! ( f. buf, ": " ) ) ;
239
218
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) ) ;
245
220
}
246
221
}
247
222
write ! ( f. buf, r"\}" )
@@ -266,7 +241,11 @@ impl<K: Hash + TotalEq, V> Mutable for LruCache<K, V> {
266
241
impl < K , V > Drop for LruCache < K , V > {
267
242
fn drop ( & mut self ) {
268
243
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) ;
270
249
}
271
250
}
272
251
}
0 commit comments