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

Side by Side Diff: net/base/expiring_cache.h

Issue 10556022: Consider the verification time as well as the expiration time when caching certificate verification… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Now with less const Created 8 years, 6 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 | « no previous file | net/base/expiring_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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #ifndef NET_BASE_EXPIRING_CACHE_H_ 5 #ifndef NET_BASE_EXPIRING_CACHE_H_
6 #define NET_BASE_EXPIRING_CACHE_H_ 6 #define NET_BASE_EXPIRING_CACHE_H_
7 #pragma once 7 #pragma once
8 8
9 #include <map> 9 #include <map>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/gtest_prod_util.h" 13 #include "base/gtest_prod_util.h"
14 #include "base/time.h" 14 #include "base/time.h"
15 15
16 namespace net { 16 namespace net {
17 17
18 // Cache implementation where all entries have an explicit expiration policy. As 18 // Cache implementation where all entries have an explicit expiration policy. As
19 // new items are added, expired items will be removed first. 19 // new items are added, expired items will be removed first.
20 // The template types have the following requirements: 20 // The template types have the following requirements:
21 // KeyType must be LessThanComparable, Assignable, and CopyConstructible. 21 // KeyType must be LessThanComparable, Assignable, and CopyConstructible.
22 // ValueType must be CopyConstructible and Assignable. 22 // ValueType must be CopyConstructible and Assignable.
23 template <typename KeyType, typename ValueType> 23 // ExpirationType must be CopyConstructible and Assignable.
24 // ExpirationCompare is a function class that takes two arguments of the
25 // type ExpirationType and returns a bool. If |comp| is an instance of
26 // ExpirationCompare, then the expression |comp(current, expiration)| shall
27 // return true iff |current| is still valid within |expiration|.
28 //
29 // A simple use of this class may use base::TimeTicks, which provides a
30 // monotonically increasing clock, for the expiration type. Because it's always
31 // increasing, std::less<> can be used, which will simply ensure that |now| is
32 // sorted before |expiration|:
33 //
34 // ExpiringCache<std::string, std::string, base::TimeTicks,
35 // std::less<base::TimeTicks> > cache(0);
36 // // Add a value that expires in 5 minutes
37 // cache.Put("key1", "value1", base::TimeTicks::Now(),
38 // base::TimeTicks::Now() + base::TimeDelta::FromMinutes(5));
39 // // Add another value that expires in 10 minutes.
40 // cache.Put("key2", "value2", base::TimeTicks::Now(),
41 // base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10));
42 //
43 // Alternatively, there may be some more complex expiration criteria, at which
44 // point a custom functor may be used:
45 //
46 // struct ComplexExpirationFunctor {
47 // bool operator()(const ComplexExpiration& now,
48 // const ComplexExpiration& expiration) const;
49 // };
50 // ExpiringCache<std::string, std::string, ComplexExpiration,
51 // ComplexExpirationFunctor> cache(15);
52 // // Add a value that expires once the 'sprocket' has 'cog'-ified.
53 // cache.Put("key1", "value1", ComplexExpiration("sprocket"),
54 // ComplexExpiration("cog"));
55 template <typename KeyType,
56 typename ValueType,
57 typename ExpirationType,
58 typename ExpirationCompare>
24 class ExpiringCache { 59 class ExpiringCache {
25 private: 60 private:
26 // Intentionally violate the C++ Style Guide so that EntryMap is known to be 61 // Intentionally violate the C++ Style Guide so that EntryMap is known to be
27 // a dependent type. Without this, Clang's two-phase lookup complains when 62 // a dependent type. Without this, Clang's two-phase lookup complains when
28 // using EntryMap::const_iterator, while GCC and MSVC happily resolve the 63 // using EntryMap::const_iterator, while GCC and MSVC happily resolve the
29 // typename. 64 // typename.
30 65
31 // Tuple to represent the value and when it expires. 66 // Tuple to represent the value and when it expires.
32 typedef std::pair<ValueType, base::TimeTicks> Entry; 67 typedef std::pair<ValueType, ExpirationType> Entry;
33 typedef std::map<KeyType, Entry> EntryMap; 68 typedef std::map<KeyType, Entry> EntryMap;
34 69
35 public: 70 public:
36 typedef KeyType key_type; 71 typedef KeyType key_type;
37 typedef ValueType value_type; 72 typedef ValueType value_type;
73 typedef ExpirationType expiration_type;
38 74
39 // This class provides a read-only iterator over items in the ExpiringCache 75 // This class provides a read-only iterator over items in the ExpiringCache
40 class Iterator { 76 class Iterator {
41 public: 77 public:
42 explicit Iterator(const ExpiringCache& cache) 78 explicit Iterator(const ExpiringCache& cache)
43 : cache_(cache), 79 : cache_(cache),
44 it_(cache_.entries_.begin()) { 80 it_(cache_.entries_.begin()) {
45 } 81 }
46 ~Iterator() {} 82 ~Iterator() {}
47 83
48 bool HasNext() const { return it_ != cache_.entries_.end(); } 84 bool HasNext() const { return it_ != cache_.entries_.end(); }
49 void Advance() { ++it_; } 85 void Advance() { ++it_; }
50 86
51 const KeyType& key() const { return it_->first; } 87 const KeyType& key() const { return it_->first; }
52 const ValueType& value() const { return it_->second.first; } 88 const ValueType& value() const { return it_->second.first; }
53 const base::TimeTicks& expiration() const { return it_->second.second; } 89 const ExpirationType& expiration() const { return it_->second.second; }
54 90
55 private: 91 private:
56 const ExpiringCache& cache_; 92 const ExpiringCache& cache_;
57 93
58 // Use a second layer of type indirection, as both EntryMap and 94 // Use a second layer of type indirection, as both EntryMap and
59 // EntryMap::const_iterator are dependent types. 95 // EntryMap::const_iterator are dependent types.
60 typedef typename ExpiringCache::EntryMap EntryMap; 96 typedef typename ExpiringCache::EntryMap EntryMap;
61 typename EntryMap::const_iterator it_; 97 typename EntryMap::const_iterator it_;
62 }; 98 };
63 99
64 100
65 // Constructs an ExpiringCache that stores up to |max_entries|. 101 // Constructs an ExpiringCache that stores up to |max_entries|.
66 explicit ExpiringCache(size_t max_entries) : max_entries_(max_entries) {} 102 explicit ExpiringCache(size_t max_entries) : max_entries_(max_entries) {}
67 ~ExpiringCache() {} 103 ~ExpiringCache() {}
68 104
69 // Returns the value matching |key|, which must be valid at the time |now|. 105 // Returns the value matching |key|, which must be valid at the time |now|.
70 // Returns NULL if the item is not found or has expired. If the item has 106 // Returns NULL if the item is not found or has expired. If the item has
71 // expired, it is immediately removed from the cache. 107 // expired, it is immediately removed from the cache.
72 // Note: The returned pointer remains owned by the ExpiringCache and is 108 // Note: The returned pointer remains owned by the ExpiringCache and is
73 // invalidated by a call to a non-const method. 109 // invalidated by a call to a non-const method.
74 const ValueType* Get(const KeyType& key, base::TimeTicks now) { 110 const ValueType* Get(const KeyType& key, const ExpirationType& now) {
75 typename EntryMap::iterator it = entries_.find(key); 111 typename EntryMap::iterator it = entries_.find(key);
76 if (it == entries_.end()) 112 if (it == entries_.end())
77 return NULL; 113 return NULL;
78 114
79 // Immediately remove expired entries. 115 // Immediately remove expired entries.
80 if (!CanUseEntry(it->second, now)) { 116 if (!expiration_comp_(now, it->second.second)) {
81 entries_.erase(it); 117 entries_.erase(it);
82 return NULL; 118 return NULL;
83 } 119 }
84 120
85 return &it->second.first; 121 return &it->second.first;
86 } 122 }
87 123
88 // Updates or replaces the value associated with |key|. 124 // Updates or replaces the value associated with |key|.
89 void Put(const KeyType& key, 125 void Put(const KeyType& key,
90 const ValueType& value, 126 const ValueType& value,
91 base::TimeTicks now, 127 const ExpirationType& now,
92 base::TimeDelta ttl) { 128 const ExpirationType& expiration) {
93 base::TimeTicks expiration = now + ttl;
94 typename EntryMap::iterator it = entries_.find(key); 129 typename EntryMap::iterator it = entries_.find(key);
95 if (it == entries_.end()) { 130 if (it == entries_.end()) {
96 // Compact the cache if it grew beyond the limit. 131 // Compact the cache if it grew beyond the limit.
97 if (entries_.size() == max_entries_ ) 132 if (entries_.size() == max_entries_ )
98 Compact(now); 133 Compact(now);
99 134
100 // No existing entry. Creating a new one. 135 // No existing entry. Creating a new one.
101 entries_.insert(std::make_pair(key, Entry(value, expiration))); 136 entries_.insert(std::make_pair(key, Entry(value, expiration)));
102 } else { 137 } else {
103 // Update an existing cache entry. 138 // Update an existing cache entry.
(...skipping 10 matching lines...) Expand all
114 // Returns the number of entries in the cache. 149 // Returns the number of entries in the cache.
115 size_t size() const { return entries_.size(); } 150 size_t size() const { return entries_.size(); }
116 151
117 // Returns the maximum number of entries in the cache. 152 // Returns the maximum number of entries in the cache.
118 size_t max_entries() const { return max_entries_; } 153 size_t max_entries() const { return max_entries_; }
119 154
120 bool empty() const { return entries_.empty(); } 155 bool empty() const { return entries_.empty(); }
121 156
122 private: 157 private:
123 FRIEND_TEST_ALL_PREFIXES(ExpiringCacheTest, Compact); 158 FRIEND_TEST_ALL_PREFIXES(ExpiringCacheTest, Compact);
124 159 FRIEND_TEST_ALL_PREFIXES(ExpiringCacheTest, CustomFunctor);
125 // Returns true if this cache entry's result is valid at time |now|.
126 static bool CanUseEntry(const Entry& entry, const base::TimeTicks now) {
127 return entry.second > now;
128 }
129 160
130 // Prunes entries from the cache to bring it below |max_entries()|. 161 // Prunes entries from the cache to bring it below |max_entries()|.
131 void Compact(base::TimeTicks now) { 162 void Compact(const ExpirationType& now) {
132 // Clear out expired entries. 163 // Clear out expired entries.
133 typename EntryMap::iterator it; 164 typename EntryMap::iterator it;
134 for (it = entries_.begin(); it != entries_.end(); ) { 165 for (it = entries_.begin(); it != entries_.end(); ) {
135 if (!CanUseEntry(it->second, now)) { 166 if (!expiration_comp_(now, it->second.second)) {
136 entries_.erase(it++); 167 entries_.erase(it++);
137 } else { 168 } else {
138 ++it; 169 ++it;
139 } 170 }
140 } 171 }
141 172
142 if (entries_.size() < max_entries_) 173 if (entries_.size() < max_entries_)
143 return; 174 return;
144 175
145 // If the cache is still too full, start deleting items 'randomly'. 176 // If the cache is still too full, start deleting items 'randomly'.
146 for (it = entries_.begin(); 177 for (it = entries_.begin();
147 it != entries_.end() && entries_.size() >= max_entries_;) { 178 it != entries_.end() && entries_.size() >= max_entries_;) {
148 entries_.erase(it++); 179 entries_.erase(it++);
149 } 180 }
150 } 181 }
151 182
152 // Bound on total size of the cache. 183 // Bound on total size of the cache.
153 size_t max_entries_; 184 size_t max_entries_;
154 185
155 EntryMap entries_; 186 EntryMap entries_;
187 ExpirationCompare expiration_comp_;
156 188
157 DISALLOW_COPY_AND_ASSIGN(ExpiringCache); 189 DISALLOW_COPY_AND_ASSIGN(ExpiringCache);
158 }; 190 };
159 191
160 } // namespace net 192 } // namespace net
161 193
162 #endif // NET_BASE_EXPIRING_CACHE_H_ 194 #endif // NET_BASE_EXPIRING_CACHE_H_
OLDNEW
« no previous file with comments | « no previous file | net/base/expiring_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698