1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 //! A cache that holds a limited number of key-value pairs. When the
13 //! capacity of the cache is exceeded, the least-recently-used
14 //! (where "used" means a look-up or putting the pair into the cache)
15 //! pair is automatically removed.
20 //! use std::collections::LruCache;
22 //! let mut cache: LruCache<int, int> = LruCache::new(2);
23 //! cache.insert(1, 10);
24 //! cache.insert(2, 20);
25 //! cache.insert(3, 30);
26 //! assert!(cache.get(&1).is_none());
27 //! assert_eq!(*cache.get(&2).unwrap(), 20);
28 //! assert_eq!(*cache.get(&3).unwrap(), 30);
30 //! cache.insert(2, 22);
31 //! assert_eq!(*cache.get(&2).unwrap(), 22);
33 //! cache.insert(6, 60);
34 //! assert!(cache.get(&3).is_none());
36 //! cache.set_capacity(1);
37 //! assert!(cache.get(&2).is_none());
40 use cmp::{PartialEq, Eq};
41 use collections::HashMap;
44 use iter::{range, Iterator, Extend};
48 use option::Option::{Some, None};
51 use result::Result::{Ok, Err};
53 // FIXME(conventions): implement iterators?
54 // FIXME(conventions): implement indexing?
56 struct KeyRef<K> { k: *const K }
58 struct LruEntry<K, V> {
59 next: *mut LruEntry<K, V>,
60 prev: *mut LruEntry<K, V>,
66 pub struct LruCache<K, V> {
67 map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>>,
69 head: *mut LruEntry<K, V>,
72 impl<S, K: Hash<S>> Hash<S> for KeyRef<K> {
73 fn hash(&self, state: &mut S) {
74 unsafe { (*self.k).hash(state) }
78 impl<K: PartialEq> PartialEq for KeyRef<K> {
79 fn eq(&self, other: &KeyRef<K>) -> bool {
80 unsafe{ (*self.k).eq(&*other.k) }
84 impl<K: Eq> Eq for KeyRef<K> {}
86 impl<K, V> LruEntry<K, V> {
87 fn new(k: K, v: V) -> LruEntry<K, V> {
91 next: ptr::null_mut(),
92 prev: ptr::null_mut(),
97 impl<K: Hash + Eq, V> LruCache<K, V> {
98 /// Create an LRU Cache that holds at most `capacity` items.
103 /// use std::collections::LruCache;
104 /// let mut cache: LruCache<int, &str> = LruCache::new(10);
106 #[unstable = "matches collection reform specification, waiting for dust to settle"]
107 pub fn new(capacity: uint) -> LruCache<K, V> {
108 let cache = LruCache {
111 head: unsafe{ mem::transmute(box mem::uninitialized::<LruEntry<K, V>>()) },
114 (*cache.head).next = cache.head;
115 (*cache.head).prev = cache.head;
120 /// Deprecated: Replaced with `insert`.
121 #[deprecated = "Replaced with `insert`"]
122 pub fn put(&mut self, k: K, v: V) {
126 /// Inserts a key-value pair into the cache. If the key already existed, the old value is
132 /// use std::collections::LruCache;
133 /// let mut cache = LruCache::new(2);
135 /// cache.insert(1i, "a");
136 /// cache.insert(2, "b");
137 /// assert_eq!(cache.get(&1), Some(&"a"));
138 /// assert_eq!(cache.get(&2), Some(&"b"));
140 #[unstable = "matches collection reform specification, waiting for dust to settle"]
141 pub fn insert(&mut self, k: K, v: V) -> Option<V> {
142 let (node_ptr, node_opt, old_val) = match self.map.get_mut(&KeyRef{k: &k}) {
144 let old_val = mem::replace(&mut node.value, v);
145 let node_ptr: *mut LruEntry<K, V> = &mut **node;
146 (node_ptr, None, Some(old_val))
149 let mut node = box LruEntry::new(k, v);
150 let node_ptr: *mut LruEntry<K, V> = &mut *node;
151 (node_ptr, Some(node), None)
156 // Existing node, just update LRU position
157 self.detach(node_ptr);
158 self.attach(node_ptr);
161 let keyref = unsafe { &(*node_ptr).key };
162 self.map.insert(KeyRef{k: keyref}, node);
163 self.attach(node_ptr);
164 if self.len() > self.capacity() {
172 /// Return a value corresponding to the key in the cache.
177 /// use std::collections::LruCache;
178 /// let mut cache = LruCache::new(2);
180 /// cache.insert(1i, "a");
181 /// cache.insert(2, "b");
182 /// cache.insert(2, "c");
183 /// cache.insert(3, "d");
185 /// assert_eq!(cache.get(&1), None);
186 /// assert_eq!(cache.get(&2), Some(&"c"));
188 #[unstable = "matches collection reform specification, waiting for dust to settle"]
189 pub fn get(&mut self, k: &K) -> Option<&V> {
190 let (value, node_ptr_opt) = match self.map.get_mut(&KeyRef{k: k}) {
191 None => (None, None),
193 let node_ptr: *mut LruEntry<K, V> = &mut **node;
194 (Some(unsafe { &(*node_ptr).value }), Some(node_ptr))
200 self.detach(node_ptr);
201 self.attach(node_ptr);
207 /// Deprecated: Renamed to `remove`.
208 #[deprecated = "Renamed to `remove`"]
209 pub fn pop(&mut self, k: &K) -> Option<V> {
213 /// Remove and return a value corresponding to the key from the cache.
218 /// use std::collections::LruCache;
219 /// let mut cache = LruCache::new(2);
221 /// cache.insert(2i, "a");
223 /// assert_eq!(cache.remove(&1), None);
224 /// assert_eq!(cache.remove(&2), Some("a"));
225 /// assert_eq!(cache.remove(&2), None);
226 /// assert_eq!(cache.len(), 0);
228 #[unstable = "matches collection reform specification, waiting for dust to settle"]
229 pub fn remove(&mut self, k: &K) -> Option<V> {
230 match self.map.remove(&KeyRef{k: k}) {
232 Some(lru_entry) => Some(lru_entry.value)
236 /// Return the maximum number of key-value pairs the cache can hold.
241 /// use std::collections::LruCache;
242 /// let mut cache: LruCache<int, &str> = LruCache::new(2);
243 /// assert_eq!(cache.capacity(), 2);
245 #[unstable = "matches collection reform specification, waiting for dust to settle"]
246 pub fn capacity(&self) -> uint {
250 /// Deprecated: Renamed to `set_capacity`.
251 #[deprecated = "Renamed to `set_capacity`"]
252 pub fn change_capacity(&mut self, capacity: uint) {
253 self.set_capacity(capacity)
256 /// Change the number of key-value pairs the cache can hold. Remove
257 /// least-recently-used key-value pairs if necessary.
262 /// use std::collections::LruCache;
263 /// let mut cache = LruCache::new(2);
265 /// cache.insert(1i, "a");
266 /// cache.insert(2, "b");
267 /// cache.insert(3, "c");
269 /// assert_eq!(cache.get(&1), None);
270 /// assert_eq!(cache.get(&2), Some(&"b"));
271 /// assert_eq!(cache.get(&3), Some(&"c"));
273 /// cache.set_capacity(3);
274 /// cache.insert(1i, "a");
275 /// cache.insert(2, "b");
277 /// assert_eq!(cache.get(&1), Some(&"a"));
278 /// assert_eq!(cache.get(&2), Some(&"b"));
279 /// assert_eq!(cache.get(&3), Some(&"c"));
281 /// cache.set_capacity(1);
283 /// assert_eq!(cache.get(&1), None);
284 /// assert_eq!(cache.get(&2), None);
285 /// assert_eq!(cache.get(&3), Some(&"c"));
287 #[unstable = "matches collection reform specification, waiting for dust to settle"]
288 pub fn set_capacity(&mut self, capacity: uint) {
289 for _ in range(capacity, self.len()) {
292 self.max_size = capacity;
296 fn remove_lru(&mut self) {
298 let lru = unsafe { (*self.head).prev };
300 self.map.remove(&KeyRef{k: unsafe { &(*lru).key }});
305 fn detach(&mut self, node: *mut LruEntry<K, V>) {
307 (*(*node).prev).next = (*node).next;
308 (*(*node).next).prev = (*node).prev;
313 fn attach(&mut self, node: *mut LruEntry<K, V>) {
315 (*node).next = (*self.head).next;
316 (*node).prev = self.head;
317 (*self.head).next = node;
318 (*(*node).next).prev = node;
322 /// Return the number of key-value pairs in the cache.
323 #[unstable = "matches collection reform specification, waiting for dust to settle"]
324 pub fn len(&self) -> uint { self.map.len() }
326 /// Returns whether the cache is currently empty.
327 #[unstable = "matches collection reform specification, waiting for dust to settle"]
328 pub fn is_empty(&self) -> bool { self.len() == 0 }
330 /// Clear the cache of all key-value pairs.
331 #[unstable = "matches collection reform specification, waiting for dust to settle"]
332 pub fn clear(&mut self) { self.map.clear(); }
336 impl<K: Hash + Eq, V> Extend<(K, V)> for LruCache<K, V> {
337 fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
344 impl<A: fmt::Show + Hash + Eq, B: fmt::Show> fmt::Show for LruCache<A, B> {
345 /// Return a string that lists the key-value pairs from most-recently
346 /// used to least-recently used.
347 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
348 try!(write!(f, "{{"));
349 let mut cur = self.head;
350 for i in range(0, self.len()) {
351 if i > 0 { try!(write!(f, ", ")) }
354 try!(write!(f, "{}", (*cur).key));
356 try!(write!(f, ": "));
358 try!(write!(f, "{}", (*cur).value));
366 impl<K, V> Drop for LruCache<K, V> {
369 let node: Box<LruEntry<K, V>> = mem::transmute(self.head);
370 // Prevent compiler from trying to drop the un-initialized field in the sigil node.
371 let box internal_node = node;
372 let LruEntry { next: _, prev: _, key: k, value: v } = internal_node;
384 fn assert_opt_eq<V: PartialEq>(opt: Option<&V>, v: V) {
385 assert!(opt.is_some());
386 assert!(opt.unwrap() == &v);
390 fn test_put_and_get() {
391 let mut cache: LruCache<int, int> = LruCache::new(2);
394 assert_opt_eq(cache.get(&1), 10);
395 assert_opt_eq(cache.get(&2), 20);
396 assert_eq!(cache.len(), 2);
400 fn test_put_update() {
401 let mut cache: LruCache<String, Vec<u8>> = LruCache::new(1);
402 cache.insert("1".to_string(), vec![10, 10]);
403 cache.insert("1".to_string(), vec![10, 19]);
404 assert_opt_eq(cache.get(&"1".to_string()), vec![10, 19]);
405 assert_eq!(cache.len(), 1);
409 fn test_expire_lru() {
410 let mut cache: LruCache<String, String> = LruCache::new(2);
411 cache.insert("foo1".to_string(), "bar1".to_string());
412 cache.insert("foo2".to_string(), "bar2".to_string());
413 cache.insert("foo3".to_string(), "bar3".to_string());
414 assert!(cache.get(&"foo1".to_string()).is_none());
415 cache.insert("foo2".to_string(), "bar2update".to_string());
416 cache.insert("foo4".to_string(), "bar4".to_string());
417 assert!(cache.get(&"foo3".to_string()).is_none());
422 let mut cache: LruCache<int, int> = LruCache::new(2);
425 assert_eq!(cache.len(), 2);
426 let opt1 = cache.remove(&1);
427 assert!(opt1.is_some());
428 assert_eq!(opt1.unwrap(), 10);
429 assert!(cache.get(&1).is_none());
430 assert_eq!(cache.len(), 1);
434 fn test_change_capacity() {
435 let mut cache: LruCache<int, int> = LruCache::new(2);
436 assert_eq!(cache.capacity(), 2);
439 cache.set_capacity(1);
440 assert!(cache.get(&1).is_none());
441 assert_eq!(cache.capacity(), 1);
445 fn test_to_string() {
446 let mut cache: LruCache<int, int> = LruCache::new(3);
450 assert_eq!(cache.to_string(), "{3: 30, 2: 20, 1: 10}");
452 assert_eq!(cache.to_string(), "{2: 22, 3: 30, 1: 10}");
454 assert_eq!(cache.to_string(), "{6: 60, 2: 22, 3: 30}");
456 assert_eq!(cache.to_string(), "{3: 30, 6: 60, 2: 22}");
457 cache.set_capacity(2);
458 assert_eq!(cache.to_string(), "{3: 30, 6: 60}");
463 let mut cache: LruCache<int, int> = LruCache::new(2);
467 assert!(cache.get(&1).is_none());
468 assert!(cache.get(&2).is_none());
469 assert_eq!(cache.to_string(), "{}");