OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains a template for a Most Recently Used cache that allows | 5 // This file contains a template for a Most Recently Used cache that allows |
6 // constant-time access to items using a key, but easy identification of the | 6 // constant-time access to items using a key, but easy identification of the |
7 // least-recently-used items for removal. Each key can only be associated with | 7 // least-recently-used items for removal. Each key can only be associated with |
8 // one payload item at a time. | 8 // one payload item at a time. |
9 // | 9 // |
10 // The key object will be stored twice, so it should support efficient copying. | 10 // The key object will be stored twice, so it should support efficient copying. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 } | 63 } |
64 | 64 |
65 // Inserts a payload item with the given key. If an existing item has | 65 // Inserts a payload item with the given key. If an existing item has |
66 // the same key, it is removed prior to insertion. An iterator indicating the | 66 // the same key, it is removed prior to insertion. An iterator indicating the |
67 // inserted item will be returned (this will always be the front of the list). | 67 // inserted item will be returned (this will always be the front of the list). |
68 // | 68 // |
69 // The payload will be copied. In the case of an OwningMRUCache, this function | 69 // The payload will be copied. In the case of an OwningMRUCache, this function |
70 // will take ownership of the pointer. | 70 // will take ownership of the pointer. |
71 iterator Put(const KeyType& key, const PayloadType& payload) { | 71 iterator Put(const KeyType& key, const PayloadType& payload) { |
72 // Remove any existing payload with that key. | 72 // Remove any existing payload with that key. |
73 KeyIndex::iterator index_iter = index_.find(key); | 73 typename KeyIndex::iterator index_iter = index_.find(key); |
74 if (index_iter != index_.end()) { | 74 if (index_iter != index_.end()) { |
75 // Erase the reference to it. This will call the deletor on the removed | 75 // Erase the reference to it. This will call the deletor on the removed |
76 // element. The index reference will be replaced in the code below. | 76 // element. The index reference will be replaced in the code below. |
77 Erase(index_iter->second); | 77 Erase(index_iter->second); |
78 } else if (max_size_ != NO_AUTO_EVICT) { | 78 } else if (max_size_ != NO_AUTO_EVICT) { |
79 // New item is being inserted which might make it larger than the maximum | 79 // New item is being inserted which might make it larger than the maximum |
80 // size: kick the oldest thing out if necessary. | 80 // size: kick the oldest thing out if necessary. |
81 ShrinkToSize(max_size_ - 1); | 81 ShrinkToSize(max_size_ - 1); |
82 } | 82 } |
83 | 83 |
84 ordering_.push_front(value_type(key, payload)); | 84 ordering_.push_front(value_type(key, payload)); |
85 index_[key] = ordering_.begin(); | 85 index_[key] = ordering_.begin(); |
86 return ordering_.begin(); | 86 return ordering_.begin(); |
87 } | 87 } |
88 | 88 |
89 // Retrieves the contents of the given key, or end() if not found. This method | 89 // Retrieves the contents of the given key, or end() if not found. This method |
90 // has the side effect of moving the requested item to the front of the | 90 // has the side effect of moving the requested item to the front of the |
91 // recency list. | 91 // recency list. |
92 // | 92 // |
93 // TODO(brettw) We may want a const version of this function in the future. | 93 // TODO(brettw) We may want a const version of this function in the future. |
94 iterator Get(const KeyType& key) { | 94 iterator Get(const KeyType& key) { |
95 KeyIndex::iterator index_iter = index_.find(key); | 95 typename KeyIndex::iterator index_iter = index_.find(key); |
96 if (index_iter == index_.end()) | 96 if (index_iter == index_.end()) |
97 return end(); | 97 return end(); |
98 PayloadList::iterator iter = index_iter->second; | 98 typename PayloadList::iterator iter = index_iter->second; |
99 | 99 |
100 // Move the touched item to the front of the recency ordering. | 100 // Move the touched item to the front of the recency ordering. |
101 ordering_.splice(ordering_.begin(), ordering_, iter); | 101 ordering_.splice(ordering_.begin(), ordering_, iter); |
102 return ordering_.begin(); | 102 return ordering_.begin(); |
103 } | 103 } |
104 | 104 |
105 // Retrieves the payload associated with a given key and returns it via | 105 // Retrieves the payload associated with a given key and returns it via |
106 // result without affecting the ordering (unlike Get). | 106 // result without affecting the ordering (unlike Get). |
107 // | 107 // |
108 // TODO(brettw) We may want a const version of this function in the future. | 108 // TODO(brettw) We may want a const version of this function in the future. |
109 iterator Peek(const KeyType& key) { | 109 iterator Peek(const KeyType& key) { |
110 KeyIndex::const_iterator index_iter = index_.find(key); | 110 typename KeyIndex::const_iterator index_iter = index_.find(key); |
111 if (index_iter == index_.end()) | 111 if (index_iter == index_.end()) |
112 return end(); | 112 return end(); |
113 return index_iter->second; | 113 return index_iter->second; |
114 } | 114 } |
115 | 115 |
116 // Erases the item referenced by the given iterator. An iterator to the item | 116 // Erases the item referenced by the given iterator. An iterator to the item |
117 // following it will be returned. The iterator must be valid. | 117 // following it will be returned. The iterator must be valid. |
118 iterator Erase(iterator pos) { | 118 iterator Erase(iterator pos) { |
119 deletor_(pos->second); | 119 deletor_(pos->second); |
120 index_.erase(pos->first); | 120 index_.erase(pos->first); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 void operator()(PayloadType& payload) { | 183 void operator()(PayloadType& payload) { |
184 } | 184 } |
185 }; | 185 }; |
186 | 186 |
187 // A container that does not do anything to free its data. Use this when storing | 187 // A container that does not do anything to free its data. Use this when storing |
188 // value types (as opposed to pointers) in the list. | 188 // value types (as opposed to pointers) in the list. |
189 template <class KeyType, class PayloadType> | 189 template <class KeyType, class PayloadType> |
190 class MRUCache : public MRUCacheBase<KeyType, | 190 class MRUCache : public MRUCacheBase<KeyType, |
191 PayloadType, | 191 PayloadType, |
192 MRUCacheNullDeletor<PayloadType> > { | 192 MRUCacheNullDeletor<PayloadType> > { |
| 193 private: |
| 194 typedef MRUCacheBase<KeyType, PayloadType, |
| 195 MRUCacheNullDeletor<PayloadType> > ParentType; |
| 196 |
193 public: | 197 public: |
194 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. | 198 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. |
195 MRUCache(size_type max_size) : MRUCacheBase(max_size) { | 199 MRUCache(typename ParentType::size_type max_size) |
| 200 : ParentType(max_size) { |
196 } | 201 } |
197 virtual ~MRUCache() { | 202 virtual ~MRUCache() { |
198 } | 203 } |
199 | 204 |
200 private: | 205 private: |
201 DISALLOW_EVIL_CONSTRUCTORS(MRUCache); | 206 DISALLOW_COPY_AND_ASSIGN(MRUCache); |
202 }; | 207 }; |
203 | 208 |
204 // OwningMRUCache -------------------------------------------------------------- | 209 // OwningMRUCache -------------------------------------------------------------- |
205 | 210 |
206 template<class PayloadType> | 211 template<class PayloadType> |
207 class MRUCachePointerDeletor { | 212 class MRUCachePointerDeletor { |
208 public: | 213 public: |
209 void operator()(PayloadType& payload) { | 214 void operator()(PayloadType& payload) { |
210 delete payload; | 215 delete payload; |
211 } | 216 } |
212 }; | 217 }; |
213 | 218 |
214 // A cache that owns the payload type, which must be a non-const pointer type. | 219 // A cache that owns the payload type, which must be a non-const pointer type. |
215 // The pointers will be deleted when they are removed, replaced, or when the | 220 // The pointers will be deleted when they are removed, replaced, or when the |
216 // cache is destroyed. | 221 // cache is destroyed. |
217 template <class KeyType, class PayloadType> | 222 template <class KeyType, class PayloadType> |
218 class OwningMRUCache | 223 class OwningMRUCache |
219 : public MRUCacheBase<KeyType, | 224 : public MRUCacheBase<KeyType, |
220 PayloadType, | 225 PayloadType, |
221 MRUCachePointerDeletor<PayloadType> > { | 226 MRUCachePointerDeletor<PayloadType> > { |
| 227 private: |
| 228 typedef MRUCacheBase<KeyType, PayloadType, |
| 229 MRUCachePointerDeletor<PayloadType> > ParentType; |
| 230 |
222 public: | 231 public: |
223 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. | 232 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. |
224 OwningMRUCache(size_type max_size) : MRUCacheBase(max_size) { | 233 OwningMRUCache(typename ParentType::size_type max_size) |
| 234 : ParentType(max_size) { |
225 } | 235 } |
226 virtual ~OwningMRUCache() { | 236 virtual ~OwningMRUCache() { |
227 } | 237 } |
228 | 238 |
229 private: | 239 private: |
230 DISALLOW_EVIL_CONSTRUCTORS(OwningMRUCache); | 240 DISALLOW_COPY_AND_ASSIGN(OwningMRUCache); |
231 }; | 241 }; |
232 | 242 |
233 #endif // CHROME_COMMON_MRU_CACHE_H__ | 243 #endif // CHROME_COMMON_MRU_CACHE_H__ |
234 | 244 |
OLD | NEW |