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

Side by Side Diff: chrome/common/mru_cache.h

Issue 6677096: Move a bunch of files from chrome\common to content\common. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 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 | Annotate | Revision Log
« no previous file with comments | « chrome/common/geoposition.cc ('k') | chrome/common/mru_cache_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
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
7 // least-recently-used items for removal. Each key can only be associated with
8 // one payload item at a time.
9 //
10 // The key object will be stored twice, so it should support efficient copying.
11 //
12 // NOTE: While all operations are O(1), this code is written for
13 // legibility rather than optimality. If future profiling identifies this as
14 // a bottleneck, there is room for smaller values of 1 in the O(1). :]
15
16 #ifndef CHROME_COMMON_MRU_CACHE_H__
17 #define CHROME_COMMON_MRU_CACHE_H__
18 #pragma once
19
20 #include <list>
21 #include <map>
22 #include <utility>
23
24 #include "base/basictypes.h"
25 #include "base/logging.h"
26
27 // MRUCacheBase ----------------------------------------------------------------
28
29 // Base class for the MRU cache specializations defined below.
30 // The deletor will get called on all payloads that are being removed or
31 // replaced.
32 template <class KeyType, class PayloadType, class DeletorType>
33 class MRUCacheBase {
34 public:
35 // The payload of the list. This maintains a copy of the key so we can
36 // efficiently delete things given an element of the list.
37 typedef std::pair<KeyType, PayloadType> value_type;
38
39 private:
40 typedef std::list<value_type> PayloadList;
41 typedef std::map<KeyType, typename PayloadList::iterator> KeyIndex;
42
43 public:
44 typedef typename PayloadList::size_type size_type;
45
46 typedef typename PayloadList::iterator iterator;
47 typedef typename PayloadList::const_iterator const_iterator;
48 typedef typename PayloadList::reverse_iterator reverse_iterator;
49 typedef typename PayloadList::const_reverse_iterator const_reverse_iterator;
50
51 enum { NO_AUTO_EVICT = 0 };
52
53 // The max_size is the size at which the cache will prune its members to when
54 // a new item is inserted. If the caller wants to manager this itself (for
55 // example, maybe it has special work to do when something is evicted), it
56 // can pass NO_AUTO_EVICT to not restrict the cache size.
57 explicit MRUCacheBase(size_type max_size) : max_size_(max_size) {
58 }
59
60 virtual ~MRUCacheBase() {
61 iterator i = begin();
62 while (i != end())
63 i = Erase(i);
64 }
65
66 // Inserts a payload item with the given key. If an existing item has
67 // the same key, it is removed prior to insertion. An iterator indicating the
68 // inserted item will be returned (this will always be the front of the list).
69 //
70 // The payload will be copied. In the case of an OwningMRUCache, this function
71 // will take ownership of the pointer.
72 iterator Put(const KeyType& key, const PayloadType& payload) {
73 // Remove any existing payload with that key.
74 typename KeyIndex::iterator index_iter = index_.find(key);
75 if (index_iter != index_.end()) {
76 // Erase the reference to it. This will call the deletor on the removed
77 // element. The index reference will be replaced in the code below.
78 Erase(index_iter->second);
79 } else if (max_size_ != NO_AUTO_EVICT) {
80 // New item is being inserted which might make it larger than the maximum
81 // size: kick the oldest thing out if necessary.
82 ShrinkToSize(max_size_ - 1);
83 }
84
85 ordering_.push_front(value_type(key, payload));
86 index_[key] = ordering_.begin();
87 return ordering_.begin();
88 }
89
90 // Retrieves the contents of the given key, or end() if not found. This method
91 // has the side effect of moving the requested item to the front of the
92 // recency list.
93 //
94 // TODO(brettw) We may want a const version of this function in the future.
95 iterator Get(const KeyType& key) {
96 typename KeyIndex::iterator index_iter = index_.find(key);
97 if (index_iter == index_.end())
98 return end();
99 typename PayloadList::iterator iter = index_iter->second;
100
101 // Move the touched item to the front of the recency ordering.
102 ordering_.splice(ordering_.begin(), ordering_, iter);
103 return ordering_.begin();
104 }
105
106 // Retrieves the payload associated with a given key and returns it via
107 // result without affecting the ordering (unlike Get).
108 //
109 // TODO(brettw) We may want a const version of this function in the future.
110 iterator Peek(const KeyType& key) {
111 typename KeyIndex::const_iterator index_iter = index_.find(key);
112 if (index_iter == index_.end())
113 return end();
114 return index_iter->second;
115 }
116
117 // Erases the item referenced by the given iterator. An iterator to the item
118 // following it will be returned. The iterator must be valid.
119 iterator Erase(iterator pos) {
120 deletor_(pos->second);
121 index_.erase(pos->first);
122 return ordering_.erase(pos);
123 }
124
125 // MRUCache entries are often processed in reverse order, so we add this
126 // convenience function (not typically defined by STL containers).
127 reverse_iterator Erase(reverse_iterator pos) {
128 // We have to actually give it the incremented iterator to delete, since
129 // the forward iterator that base() returns is actually one past the item
130 // being iterated over.
131 return reverse_iterator(Erase((++pos).base()));
132 }
133
134 // Shrinks the cache so it only holds |new_size| items. If |new_size| is
135 // bigger or equal to the current number of items, this will do nothing.
136 void ShrinkToSize(size_type new_size) {
137 for (size_type i = size(); i > new_size; i--)
138 Erase(rbegin());
139 }
140
141 // Deletes everything from the cache.
142 void Clear() {
143 for (typename PayloadList::iterator i(ordering_.begin());
144 i != ordering_.end(); ++i)
145 deletor_(i->second);
146 index_.clear();
147 ordering_.clear();
148 }
149
150 // Returns the number of elements in the cache.
151 size_type size() const {
152 // We don't use ordering_.size() for the return value because
153 // (as a linked list) it can be O(n).
154 DCHECK(index_.size() == ordering_.size());
155 return index_.size();
156 }
157
158 // Allows iteration over the list. Forward iteration starts with the most
159 // recent item and works backwards.
160 //
161 // Note that since these iterators are actually iterators over a list, you
162 // can keep them as you insert or delete things (as long as you don't delete
163 // the one you are pointing to) and they will still be valid.
164 iterator begin() { return ordering_.begin(); }
165 const_iterator begin() const { ordering_.begin(); }
166 iterator end() { return ordering_.end(); }
167 const_iterator end() const { return ordering_.end(); }
168
169 reverse_iterator rbegin() { return ordering_.rbegin(); }
170 const_reverse_iterator rbegin() const { ordering_.rbegin(); }
171 reverse_iterator rend() { return ordering_.rend(); }
172 const_reverse_iterator rend() const { return ordering_.rend(); }
173
174 bool empty() const { return ordering_.empty(); }
175
176 private:
177 PayloadList ordering_;
178 KeyIndex index_;
179
180 size_type max_size_;
181
182 DeletorType deletor_;
183
184 DISALLOW_COPY_AND_ASSIGN(MRUCacheBase);
185 };
186
187 // MRUCache --------------------------------------------------------------------
188
189 // A functor that does nothing. Used by the MRUCache.
190 template<class PayloadType>
191 class MRUCacheNullDeletor {
192 public:
193 void operator()(PayloadType& payload) {
194 }
195 };
196
197 // A container that does not do anything to free its data. Use this when storing
198 // value types (as opposed to pointers) in the list.
199 template <class KeyType, class PayloadType>
200 class MRUCache : public MRUCacheBase<KeyType,
201 PayloadType,
202 MRUCacheNullDeletor<PayloadType> > {
203 private:
204 typedef MRUCacheBase<KeyType, PayloadType,
205 MRUCacheNullDeletor<PayloadType> > ParentType;
206
207 public:
208 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
209 explicit MRUCache(typename ParentType::size_type max_size)
210 : ParentType(max_size) {
211 }
212 virtual ~MRUCache() {
213 }
214
215 private:
216 DISALLOW_COPY_AND_ASSIGN(MRUCache);
217 };
218
219 // OwningMRUCache --------------------------------------------------------------
220
221 template<class PayloadType>
222 class MRUCachePointerDeletor {
223 public:
224 void operator()(PayloadType& payload) {
225 delete payload;
226 }
227 };
228
229 // A cache that owns the payload type, which must be a non-const pointer type.
230 // The pointers will be deleted when they are removed, replaced, or when the
231 // cache is destroyed.
232 template <class KeyType, class PayloadType>
233 class OwningMRUCache
234 : public MRUCacheBase<KeyType,
235 PayloadType,
236 MRUCachePointerDeletor<PayloadType> > {
237 private:
238 typedef MRUCacheBase<KeyType, PayloadType,
239 MRUCachePointerDeletor<PayloadType> > ParentType;
240
241 public:
242 // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
243 explicit OwningMRUCache(typename ParentType::size_type max_size)
244 : ParentType(max_size) {
245 }
246 virtual ~OwningMRUCache() {
247 }
248
249 private:
250 DISALLOW_COPY_AND_ASSIGN(OwningMRUCache);
251 };
252
253 #endif // CHROME_COMMON_MRU_CACHE_H__
OLDNEW
« no previous file with comments | « chrome/common/geoposition.cc ('k') | chrome/common/mru_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698