Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: base/containers/mru_cache.h

Issue 1763273002: base: Remove OwningMRUCache in favor of scoped_ptrs in MRUCache (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase + fix Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 23 matching lines...) Expand all
34 34
35 // This template is used to standardize map type containers that can be used 35 // This template is used to standardize map type containers that can be used
36 // by MRUCacheBase. This level of indirection is necessary because of the way 36 // by MRUCacheBase. This level of indirection is necessary because of the way
37 // that template template params and default template params interact. 37 // that template template params and default template params interact.
38 template <class KeyType, class ValueType, class CompareType> 38 template <class KeyType, class ValueType, class CompareType>
39 struct MRUCacheStandardMap { 39 struct MRUCacheStandardMap {
40 typedef std::map<KeyType, ValueType, CompareType> Type; 40 typedef std::map<KeyType, ValueType, CompareType> Type;
41 }; 41 };
42 42
43 // Base class for the MRU cache specializations defined below. 43 // Base class for the MRU cache specializations defined below.
44 // The deletor will get called on all payloads that are being removed or
45 // replaced.
46 template <class KeyType, 44 template <class KeyType,
47 class PayloadType, 45 class PayloadType,
48 class HashOrCompareType, 46 class HashOrCompareType,
49 class DeletorType,
50 template <typename, typename, typename> class MapType = 47 template <typename, typename, typename> class MapType =
51 MRUCacheStandardMap> 48 MRUCacheStandardMap>
52 class MRUCacheBase { 49 class MRUCacheBase {
53 public: 50 public:
54 // The payload of the list. This maintains a copy of the key so we can 51 // The payload of the list. This maintains a copy of the key so we can
55 // efficiently delete things given an element of the list. 52 // efficiently delete things given an element of the list.
56 typedef std::pair<KeyType, PayloadType> value_type; 53 typedef std::pair<KeyType, PayloadType> value_type;
57 54
58 private: 55 private:
59 typedef std::list<value_type> PayloadList; 56 typedef std::list<value_type> PayloadList;
60 typedef typename MapType<KeyType, 57 typedef typename MapType<KeyType,
61 typename PayloadList::iterator, 58 typename PayloadList::iterator,
62 HashOrCompareType>::Type KeyIndex; 59 HashOrCompareType>::Type KeyIndex;
63 60
64 public: 61 public:
65 typedef typename PayloadList::size_type size_type; 62 typedef typename PayloadList::size_type size_type;
66 63
67 typedef typename PayloadList::iterator iterator; 64 typedef typename PayloadList::iterator iterator;
68 typedef typename PayloadList::const_iterator const_iterator; 65 typedef typename PayloadList::const_iterator const_iterator;
69 typedef typename PayloadList::reverse_iterator reverse_iterator; 66 typedef typename PayloadList::reverse_iterator reverse_iterator;
70 typedef typename PayloadList::const_reverse_iterator const_reverse_iterator; 67 typedef typename PayloadList::const_reverse_iterator const_reverse_iterator;
71 68
72 enum { NO_AUTO_EVICT = 0 }; 69 enum { NO_AUTO_EVICT = 0 };
73 70
74 // The max_size is the size at which the cache will prune its members to when 71 // The max_size is the size at which the cache will prune its members to when
75 // a new item is inserted. If the caller wants to manager this itself (for 72 // a new item is inserted. If the caller wants to manager this itself (for
76 // example, maybe it has special work to do when something is evicted), it 73 // example, maybe it has special work to do when something is evicted), it
77 // can pass NO_AUTO_EVICT to not restrict the cache size. 74 // can pass NO_AUTO_EVICT to not restrict the cache size.
78 explicit MRUCacheBase(size_type max_size) : max_size_(max_size) { 75 explicit MRUCacheBase(size_type max_size) : max_size_(max_size) {}
79 }
80 76
81 MRUCacheBase(size_type max_size, const DeletorType& deletor) 77 virtual ~MRUCacheBase() {}
82 : max_size_(max_size), deletor_(deletor) {
83 }
84
85 virtual ~MRUCacheBase() {
86 iterator i = begin();
87 while (i != end())
88 i = Erase(i);
89 }
90 78
91 size_type max_size() const { return max_size_; } 79 size_type max_size() const { return max_size_; }
92 80
93 // Inserts a payload item with the given key. If an existing item has 81 // Inserts a payload item with the given key. If an existing item has
94 // the same key, it is removed prior to insertion. An iterator indicating the 82 // the same key, it is removed prior to insertion. An iterator indicating the
95 // inserted item will be returned (this will always be the front of the list). 83 // inserted item will be returned (this will always be the front of the list).
96 // 84 //
97 // The payload will be copied. In the case of an OwningMRUCache, this function 85 // The payload will be forwarded.
98 // will take ownership of the pointer. 86 template <typename Payload>
99 iterator Put(const KeyType& key, const PayloadType& payload) { 87 iterator Put(const KeyType& key, Payload&& payload) {
100 // Remove any existing payload with that key. 88 // Remove any existing payload with that key.
101 typename KeyIndex::iterator index_iter = index_.find(key); 89 typename KeyIndex::iterator index_iter = index_.find(key);
102 if (index_iter != index_.end()) { 90 if (index_iter != index_.end()) {
103 // Erase the reference to it. This will call the deletor on the removed 91 // Erase the reference to it. The index reference will be replaced in the
104 // element. The index reference will be replaced in the code below. 92 // code below.
105 Erase(index_iter->second); 93 Erase(index_iter->second);
106 } else if (max_size_ != NO_AUTO_EVICT) { 94 } else if (max_size_ != NO_AUTO_EVICT) {
107 // New item is being inserted which might make it larger than the maximum 95 // New item is being inserted which might make it larger than the maximum
108 // size: kick the oldest thing out if necessary. 96 // size: kick the oldest thing out if necessary.
109 ShrinkToSize(max_size_ - 1); 97 ShrinkToSize(max_size_ - 1);
110 } 98 }
111 99
112 ordering_.push_front(value_type(key, payload)); 100 ordering_.push_front(value_type(key, std::forward<Payload>(payload)));
113 index_.insert(std::make_pair(key, ordering_.begin())); 101 index_.insert(std::make_pair(key, ordering_.begin()));
114 return ordering_.begin(); 102 return ordering_.begin();
115 } 103 }
116 104
117 // Retrieves the contents of the given key, or end() if not found. This method 105 // Retrieves the contents of the given key, or end() if not found. This method
118 // has the side effect of moving the requested item to the front of the 106 // has the side effect of moving the requested item to the front of the
119 // recency list. 107 // recency list.
120 // 108 //
121 // TODO(brettw) We may want a const version of this function in the future. 109 // TODO(brettw) We may want a const version of this function in the future.
122 iterator Get(const KeyType& key) { 110 iterator Get(const KeyType& key) {
(...skipping 20 matching lines...) Expand all
143 typename KeyIndex::const_iterator index_iter = index_.find(key); 131 typename KeyIndex::const_iterator index_iter = index_.find(key);
144 if (index_iter == index_.end()) 132 if (index_iter == index_.end())
145 return end(); 133 return end();
146 return index_iter->second; 134 return index_iter->second;
147 } 135 }
148 136
149 // Exchanges the contents of |this| by the contents of the |other|. 137 // Exchanges the contents of |this| by the contents of the |other|.
150 void Swap(MRUCacheBase& other) { 138 void Swap(MRUCacheBase& other) {
151 ordering_.swap(other.ordering_); 139 ordering_.swap(other.ordering_);
152 index_.swap(other.index_); 140 index_.swap(other.index_);
153 std::swap(deletor_, other.deletor_);
154 std::swap(max_size_, other.max_size_); 141 std::swap(max_size_, other.max_size_);
155 } 142 }
156 143
157 // Erases the item referenced by the given iterator. An iterator to the item 144 // Erases the item referenced by the given iterator. An iterator to the item
158 // following it will be returned. The iterator must be valid. 145 // following it will be returned. The iterator must be valid.
159 iterator Erase(iterator pos) { 146 iterator Erase(iterator pos) {
160 deletor_(pos->second);
161 index_.erase(pos->first); 147 index_.erase(pos->first);
162 return ordering_.erase(pos); 148 return ordering_.erase(pos);
163 } 149 }
164 150
165 // MRUCache entries are often processed in reverse order, so we add this 151 // MRUCache entries are often processed in reverse order, so we add this
166 // convenience function (not typically defined by STL containers). 152 // convenience function (not typically defined by STL containers).
167 reverse_iterator Erase(reverse_iterator pos) { 153 reverse_iterator Erase(reverse_iterator pos) {
168 // We have to actually give it the incremented iterator to delete, since 154 // We have to actually give it the incremented iterator to delete, since
169 // the forward iterator that base() returns is actually one past the item 155 // the forward iterator that base() returns is actually one past the item
170 // being iterated over. 156 // being iterated over.
171 return reverse_iterator(Erase((++pos).base())); 157 return reverse_iterator(Erase((++pos).base()));
172 } 158 }
173 159
174 // Shrinks the cache so it only holds |new_size| items. If |new_size| is 160 // Shrinks the cache so it only holds |new_size| items. If |new_size| is
175 // bigger or equal to the current number of items, this will do nothing. 161 // bigger or equal to the current number of items, this will do nothing.
176 void ShrinkToSize(size_type new_size) { 162 void ShrinkToSize(size_type new_size) {
177 for (size_type i = size(); i > new_size; i--) 163 for (size_type i = size(); i > new_size; i--)
178 Erase(rbegin()); 164 Erase(rbegin());
179 } 165 }
180 166
181 // Deletes everything from the cache. 167 // Deletes everything from the cache.
182 void Clear() { 168 void Clear() {
183 for (typename PayloadList::iterator i(ordering_.begin());
184 i != ordering_.end(); ++i)
185 deletor_(i->second);
186 index_.clear(); 169 index_.clear();
187 ordering_.clear(); 170 ordering_.clear();
188 } 171 }
189 172
190 // Returns the number of elements in the cache. 173 // Returns the number of elements in the cache.
191 size_type size() const { 174 size_type size() const {
192 // We don't use ordering_.size() for the return value because 175 // We don't use ordering_.size() for the return value because
193 // (as a linked list) it can be O(n). 176 // (as a linked list) it can be O(n).
194 DCHECK(index_.size() == ordering_.size()); 177 DCHECK(index_.size() == ordering_.size());
195 return index_.size(); 178 return index_.size();
(...skipping 16 matching lines...) Expand all
212 const_reverse_iterator rend() const { return ordering_.rend(); } 195 const_reverse_iterator rend() const { return ordering_.rend(); }
213 196
214 bool empty() const { return ordering_.empty(); } 197 bool empty() const { return ordering_.empty(); }
215 198
216 private: 199 private:
217 PayloadList ordering_; 200 PayloadList ordering_;
218 KeyIndex index_; 201 KeyIndex index_;
219 202
220 size_type max_size_; 203 size_type max_size_;
221 204
222 DeletorType deletor_;
223
224 DISALLOW_COPY_AND_ASSIGN(MRUCacheBase); 205 DISALLOW_COPY_AND_ASSIGN(MRUCacheBase);
225 }; 206 };
226 207
227 // MRUCache -------------------------------------------------------------------- 208 // MRUCache --------------------------------------------------------------------
228 209
229 // A functor that does nothing. Used by the MRUCache.
230 template<class PayloadType>
231 class MRUCacheNullDeletor {
232 public:
233 void operator()(const PayloadType& payload) {}
234 };
235
236 // A container that does not do anything to free its data. Use this when storing 210 // A container that does not do anything to free its data. Use this when storing
237 // value types (as opposed to pointers) in the list. 211 // value types (as opposed to pointers) in the list.
238 template <class KeyType, class PayloadType> 212 template <class KeyType, class PayloadType>
239 class MRUCache : public MRUCacheBase<KeyType, 213 class MRUCache : public MRUCacheBase<KeyType, PayloadType, std::less<KeyType>> {
240 PayloadType,
241 std::less<KeyType>,
242 MRUCacheNullDeletor<PayloadType>> {
243 private: 214 private:
244 typedef MRUCacheBase<KeyType, 215 using ParentType = MRUCacheBase<KeyType, PayloadType, std::less<KeyType>>;
245 PayloadType,
246 std::less<KeyType>,
247 MRUCacheNullDeletor<PayloadType>>
248 ParentType;
249 216
250 public: 217 public:
251 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. 218 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
252 explicit MRUCache(typename ParentType::size_type max_size) 219 explicit MRUCache(typename ParentType::size_type max_size)
253 : ParentType(max_size) { 220 : ParentType(max_size) {}
254 } 221 virtual ~MRUCache() {}
255 virtual ~MRUCache() {
256 }
257 222
258 private: 223 private:
259 DISALLOW_COPY_AND_ASSIGN(MRUCache); 224 DISALLOW_COPY_AND_ASSIGN(MRUCache);
260 }; 225 };
261 226
262 // OwningMRUCache --------------------------------------------------------------
263
264 template<class PayloadType>
265 class MRUCachePointerDeletor {
266 public:
267 void operator()(const PayloadType& payload) { delete payload; }
268 };
269
270 // A cache that owns the payload type, which must be a non-const pointer type.
271 // The pointers will be deleted when they are removed, replaced, or when the
272 // cache is destroyed.
273 // TODO(vmpstr): This should probably go away in favor of storing scoped_ptrs.
274 template <class KeyType, class PayloadType>
275 class OwningMRUCache
276 : public MRUCacheBase<KeyType,
277 PayloadType,
278 std::less<KeyType>,
279 MRUCachePointerDeletor<PayloadType>> {
280 private:
281 typedef MRUCacheBase<KeyType,
282 PayloadType,
283 std::less<KeyType>,
284 MRUCachePointerDeletor<PayloadType>>
285 ParentType;
286
287 public:
288 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
289 explicit OwningMRUCache(typename ParentType::size_type max_size)
290 : ParentType(max_size) {
291 }
292 virtual ~OwningMRUCache() {
293 }
294
295 private:
296 DISALLOW_COPY_AND_ASSIGN(OwningMRUCache);
297 };
298
299 // HashingMRUCache ------------------------------------------------------------ 227 // HashingMRUCache ------------------------------------------------------------
300 228
301 template <class KeyType, class ValueType, class HashType> 229 template <class KeyType, class ValueType, class HashType>
302 struct MRUCacheHashMap { 230 struct MRUCacheHashMap {
303 typedef std::unordered_map<KeyType, ValueType, HashType> Type; 231 typedef std::unordered_map<KeyType, ValueType, HashType> Type;
304 }; 232 };
305 233
306 // This class is similar to MRUCache, except that it uses std::unordered_map as 234 // This class is similar to MRUCache, except that it uses std::unordered_map as
307 // the map type instead of std::map. Note that your KeyType must be hashable to 235 // the map type instead of std::map. Note that your KeyType must be hashable to
308 // use this cache or you need to provide a hashing class. 236 // use this cache or you need to provide a hashing class.
309 template <class KeyType, class PayloadType, class HashType = std::hash<KeyType>> 237 template <class KeyType, class PayloadType, class HashType = std::hash<KeyType>>
310 class HashingMRUCache : public MRUCacheBase<KeyType, 238 class HashingMRUCache
311 PayloadType, 239 : public MRUCacheBase<KeyType, PayloadType, HashType, MRUCacheHashMap> {
312 HashType,
313 MRUCacheNullDeletor<PayloadType>,
314 MRUCacheHashMap> {
315 private: 240 private:
316 typedef MRUCacheBase<KeyType, 241 using ParentType =
317 PayloadType, 242 MRUCacheBase<KeyType, PayloadType, HashType, MRUCacheHashMap>;
318 HashType,
319 MRUCacheNullDeletor<PayloadType>,
320 MRUCacheHashMap>
321 ParentType;
322 243
323 public: 244 public:
324 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. 245 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
325 explicit HashingMRUCache(typename ParentType::size_type max_size) 246 explicit HashingMRUCache(typename ParentType::size_type max_size)
326 : ParentType(max_size) { 247 : ParentType(max_size) {}
327 } 248 virtual ~HashingMRUCache() {}
328 virtual ~HashingMRUCache() {
329 }
330 249
331 private: 250 private:
332 DISALLOW_COPY_AND_ASSIGN(HashingMRUCache); 251 DISALLOW_COPY_AND_ASSIGN(HashingMRUCache);
333 }; 252 };
334 253
335 } // namespace base 254 } // namespace base
336 255
337 #endif // BASE_CONTAINERS_MRU_CACHE_H_ 256 #endif // BASE_CONTAINERS_MRU_CACHE_H_
OLDNEW
« no previous file with comments | « no previous file | base/containers/mru_cache_unittest.cc » ('j') | chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698