Apache Mesos
boundedhashmap.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 #ifndef __STOUT_BOUNDEDHASHMAP_HPP__
13 #define __STOUT_BOUNDEDHASHMAP_HPP__
14 
15 #include <list>
16 #include <utility>
17 
18 #include <stout/check.hpp>
19 #include <stout/hashmap.hpp>
20 #include <stout/option.hpp>
21 
22 // A hashmap that contains a fixed number of entries at most. Entries
23 // are evicted in FIFO order -- i.e., when the capacity of the map is
24 // reached, the next insertion results in removing the oldest entry.
25 // Updating an entry does not change insertion order.
26 template <typename Key, typename Value>
28 {
29 public:
30  typedef std::pair<Key, Value> entry;
31  typedef std::list<entry> list;
33 
34  BoundedHashMap(size_t capacity) : capacity_(capacity) {}
35 
36  // NOTE: We don't provide `operator[]`, unlike LinkedHashMap,
37  // because it would be difficult to implement correctly for bounded
38  // maps with zero capacity.
39  void set(const Key& key, const Value& value)
40  {
41  if (capacity_ == 0) {
42  return;
43  }
44 
45  if (!keys_.contains(key)) {
46  // Insert a new list entry and get a "pointer" to its location.
47  typename list::iterator iter =
48  entries_.insert(entries_.end(), std::make_pair(key, value));
49 
50  keys_[key] = iter;
51 
52  // If the map now exceeds its capacity, remove the oldest entry.
53  // Note that removal from both std::list and hashmap does not
54  // invalidate iterators that reference other entries.
55  if (keys_.size() > capacity_) {
56  typename list::iterator firstEntry = entries_.begin();
57  keys_.erase(firstEntry->first);
58  entries_.erase(firstEntry);
59 
60  CHECK(keys_.size() == capacity_);
61  }
62  } else {
63  keys_[key]->second = value;
64  }
65  }
66 
67  Option<Value> get(const Key& key) const
68  {
69  if (keys_.contains(key)) {
70  return keys_.at(key)->second;
71  }
72  return None();
73  }
74 
75  Value& at(const Key& key)
76  {
77  return keys_.at(key)->second;
78  }
79 
80  const Value& at(const Key& key) const
81  {
82  return keys_.at(key)->second;
83  }
84 
85  bool contains(const Key& key) const
86  {
87  return keys_.contains(key);
88  }
89 
90  size_t erase(const Key& key)
91  {
92  if (keys_.contains(key)) {
93  typename list::iterator entry = keys_[key];
94  keys_.erase(key);
95  entries_.erase(entry);
96 
97  return 1;
98  }
99  return 0;
100  }
101 
102  // Returns the keys in the map in insertion order.
103  std::list<Key> keys() const
104  {
105  std::list<Key> result;
106 
107  foreach (const entry& entry, entries_) {
108  result.push_back(entry.first);
109  }
110 
111  return result;
112  }
113 
114  // Returns the values in the map in insertion order.
115  std::list<Value> values() const
116  {
117  std::list<Value> result;
118 
119  foreach (const entry& entry, entries_) {
120  result.push_back(entry.second);
121  }
122 
123  return result;
124  }
125 
126  size_t size() const
127  {
128  return keys_.size();
129  }
130 
131  bool empty() const
132  {
133  return keys_.empty();
134  }
135 
136  void clear()
137  {
138  entries_.clear();
139  keys_.clear();
140  }
141 
142  // Support for iteration; this allows using `foreachpair` and
143  // related constructs. Note that these iterate over the map in
144  // insertion order.
145  typename list::iterator begin() { return entries_.begin(); }
146  typename list::iterator end() { return entries_.end(); }
147 
148  typename list::const_iterator begin() const { return entries_.cbegin(); }
149  typename list::const_iterator end() const { return entries_.cend(); }
150 
151 private:
152  size_t capacity_;
153  list entries_; // Key-value pairs ordered by insertion order.
154  map keys_; // Map from key to "pointer" to key's location in list.
155 };
156 
157 #endif // __STOUT_BOUNDEDHASHMAP_HPP__
BoundedHashMap(size_t capacity)
Definition: boundedhashmap.hpp:34
Definition: option.hpp:29
std::pair< Key, Value > entry
Definition: boundedhashmap.hpp:30
list::const_iterator begin() const
Definition: boundedhashmap.hpp:148
Value & at(const Key &key)
Definition: boundedhashmap.hpp:75
std::list< entry > list
Definition: boundedhashmap.hpp:31
const Value & at(const Key &key) const
Definition: boundedhashmap.hpp:80
size_t size() const
Definition: boundedhashmap.hpp:126
list::iterator begin()
Definition: boundedhashmap.hpp:145
bool contains(const Key &key) const
Definition: boundedhashmap.hpp:85
std::list< Key > keys() const
Definition: boundedhashmap.hpp:103
size_t erase(const Key &key)
Definition: boundedhashmap.hpp:90
std::list< Value > values() const
Definition: boundedhashmap.hpp:115
Definition: boundedhashmap.hpp:27
Definition: none.hpp:27
void clear()
Definition: boundedhashmap.hpp:136
hashmap< Key, typename list::iterator > map
Definition: boundedhashmap.hpp:32
list::const_iterator end() const
Definition: boundedhashmap.hpp:149
bool empty() const
Definition: boundedhashmap.hpp:131
bool contains(const Key &key) const
Definition: hashmap.hpp:86
list::iterator end()
Definition: boundedhashmap.hpp:146