Apache Mesos
cache.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 
13 #ifndef __STOUT_CACHE_HPP__
14 #define __STOUT_CACHE_HPP__
15 
16 #include <functional>
17 #include <iostream>
18 #include <list>
19 #include <map>
20 #include <unordered_map>
21 #include <utility>
22 
23 #include <glog/logging.h>
24 
25 #include "none.hpp"
26 #include "option.hpp"
27 
28 // Forward declaration.
29 template <typename Key, typename Value>
30 class Cache;
31 
32 // Outputs the key/value pairs from least to most-recently used.
33 template <typename Key, typename Value>
34 std::ostream& operator<<(std::ostream& stream, const Cache<Key, Value>& c);
35 
36 
37 // Provides a least-recently used (LRU) cache of some predefined
38 // capacity. A "write" and a "read" both count as uses.
39 template <typename Key, typename Value>
40 class Cache
41 {
42 public:
43  typedef std::list<Key> list;
44  typedef std::unordered_map<
45  Key, std::pair<Value, typename list::iterator>> map;
46 
47  explicit Cache(size_t _capacity) : capacity(_capacity) {}
48 
49  void put(const Key& key, const Value& value)
50  {
51  typename map::iterator i = values.find(key);
52  if (i == values.end()) {
53  insert(key, value);
54  } else {
55  (*i).second.first = value;
56  use(i);
57  }
58  }
59 
60  Option<Value> get(const Key& key)
61  {
62  typename map::iterator i = values.find(key);
63 
64  if (i != values.end()) {
65  use(i);
66  return (*i).second.first;
67  }
68 
69  return None();
70  }
71 
72  Option<Value> erase(const Key& key)
73  {
74  typename map::iterator i = values.find(key);
75 
76  if (i != values.end()) {
77  Value value = i->second.first;
78  keys.erase(i->second.second);
79  values.erase(i);
80  return value;
81  }
82 
83  return None();
84  }
85 
86  size_t size() const { return keys.size(); }
87 
88 private:
89  // Not copyable, not assignable.
90  Cache(const Cache&);
91  Cache& operator=(const Cache&);
92 
93  // Give the operator access to our internals.
94  friend std::ostream& operator<<<>(
95  std::ostream& stream,
96  const Cache<Key, Value>& c);
97 
98  // Insert key/value into the cache.
99  void insert(const Key& key, const Value& value)
100  {
101  if (keys.size() == capacity) {
102  evict();
103  }
104 
105  // Get a "pointer" into the lru list for efficient update.
106  typename list::iterator i = keys.insert(keys.end(), key);
107 
108  // Save key/value and "pointer" into lru list.
109  values.insert(std::make_pair(key, std::make_pair(value, i)));
110  }
111 
112  // Updates the LRU ordering in the cache for the given iterator.
113  void use(const typename map::iterator& i)
114  {
115  // Move the "pointer" to the end of the lru list.
116  keys.splice(keys.end(), keys, (*i).second.second);
117 
118  // Now update the "pointer" so we can do this again.
119  (*i).second.second = --keys.end();
120  }
121 
122  // Evict the least-recently used element from the cache.
123  void evict()
124  {
125  const typename map::iterator i = values.find(keys.front());
126  CHECK(i != values.end());
127  values.erase(i);
128  keys.pop_front();
129  }
130 
131  // Size of the cache.
132  const size_t capacity;
133 
134  // Cache of values and "pointers" into the least-recently used list.
135  map values;
136 
137  // Keys ordered by least-recently used.
138  list keys;
139 };
140 
141 
142 template <typename Key, typename Value>
143 std::ostream& operator<<(std::ostream& stream, const Cache<Key, Value>& c)
144 {
146  for (i1 = c.keys.begin(); i1 != c.keys.end(); i1++) {
147  stream << *i1 << ": ";
149  i2 = c.values.find(*i1);
150  CHECK(i2 != c.values.end());
151  stream << *i2 << std::endl;
152  }
153  return stream;
154 }
155 
156 #endif // __STOUT_CACHE_HPP__
Definition: option.hpp:29
std::list< Key > list
Definition: cache.hpp:43
size_t size() const
Definition: cache.hpp:86
Definition: cache.hpp:30
void put(const Key &key, const Value &value)
Definition: cache.hpp:49
Definition: none.hpp:27
std::unordered_map< Key, std::pair< Value, typename list::iterator > > map
Definition: cache.hpp:45
Option< Value > erase(const Key &key)
Definition: cache.hpp:72
Cache(size_t _capacity)
Definition: cache.hpp:47