ddc
LRUCache.h
Go to the documentation of this file.
1 //-*- Mode: C++ -*-
2 // DDC originally by Alexey Sokirko
3 // Changes and modifications 2011-2015 by Bryan Jurish
4 //
5 // This file is part of DDC.
6 //
7 // DDC is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Lesser General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // DDC is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with DDC. If not, see <http://www.gnu.org/licenses/>.
19 //
20 
21 #ifndef DDC_LRUCACHE_H
22 #define DDC_LRUCACHE_H
23 
24 #include "../CommonLib/ddcConfig.h"
25 #include <list>
26 #include <map>
27 
28 #ifdef HAVE_PTHREAD
29 # include <pthread.h>
30 # define DDC_IFPTHREAD(x) x
31 # define DDC_IFPTHREADELSE(x,y) x
32 #else
33 # define DDC_IFPTHREAD(x)
34 # define DDC_IFPTHREADELSE(x,y) y
35 #endif
36 
37 //======================================================================
38 // Globals
39 
41 #define DDC_DEFAULT_LRU_CACHE_CAPACITY 1024
42 
43 //======================================================================
45 template<class Key, class Val>
46 class ddcLRUCache {
47 public:
48  //------------------------------------------------------------
49  // public typedefs
50 
52  typedef Key KeyT;
53 
55  typedef Val ValT;
56 
57 #if HAVE_PTHREAD
58  typedef pthread_mutex_t* MutexT;
60 #else
61  typedef void* MutexT;
63 #endif
64 
66  typedef std::pair<KeyT,ValT> ItemT;
67 
69  typedef std::list<ItemT> ListT;
70 
72  typedef std::map<KeyT, typename ListT::iterator> MapT;
73 
75  typedef typename MapT::iterator iterator;
76 
78  typedef typename MapT::const_iterator const_iterator;
79 
80 public:
81  //------------------------------------------------------------
82  // pseudo-private data (public just in case you Know What You're Doing)
83 
85  size_t m_capacity;
86 
88  size_t m_size;
89 
91  ListT m_list;
92 
94  MapT m_map;
95 
97  MutexT m_mutex;
98 
99 public:
100  //------------------------------------------------------------
101  // public methods: constructors etc
102 
103  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106  : m_capacity(capacity),
107  m_size(0),
108  m_mutex(mutex)
109  {};
110 
111  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113  void clear()
114  {
115  m_map.clear();
116  m_list.clear();
117  m_size = 0;
118  };
119 
120  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
122  void clean()
123  {
124  while (m_size > m_capacity) {
125  const ItemT &lru_item = m_list.back();
126  m_map.erase(lru_item.first);
127  m_list.pop_back();
128  --m_size;
129  }
130  };
131 
132  //------------------------------------------------------------
133  // public methods: basic accessors
134 
136  inline MutexT mutex() const
137  { return m_mutex; };
138 
140  inline MutexT mutex(MutexT mut)
141  { return m_mutex=mut; };
142 
144  inline size_t size() const
145  { return m_size; };
146 
148  inline size_t capacity() const
149  { return m_capacity; };
150 
152  inline size_t reserve(size_t cap)
153  {
154  m_capacity=cap;
155  clean();
156  return m_capacity;
157  };
158 
159  //------------------------------------------------------------
160  // public methods: locking
161 
163  inline void lock()
164  { DDC_IFPTHREAD(if (m_mutex) pthread_mutex_lock(m_mutex)); };
165 
167  inline void unlock()
168  { DDC_IFPTHREAD(if (m_mutex) pthread_mutex_unlock(m_mutex)); };
169 
170  //------------------------------------------------------------
171  // public methods: map iterators
172 
173  inline iterator begin() { return m_map.begin(); };
174  inline iterator end() { return m_map.end(); };
175  inline const_iterator begin() const { return m_map.begin(); };
176  inline const_iterator end() const { return m_map.end(); };
177 
178  //------------------------------------------------------------
179  // public methods: lookup (no implicit locking; use must call lock() and unlock() if and when appropriate)
180 
182  inline iterator find(const KeyT &key)
183  { return m_map.find(key); };
184 
186  inline iterator lower_bound(const KeyT &key)
187  { return m_map.lower_bound(key); };
188 
190  inline iterator upper_bound(const KeyT &key)
191  { return m_map.upper_bound(key); };
192 
194  inline const_iterator find(const KeyT &key) const
195  { return m_map.find(key); };
196 
198  inline const_iterator lower_bound(const KeyT &key) const
199  { return m_map.lower_bound(key); };
200 
202  inline const_iterator upper_bound(const KeyT &key) const
203  { return m_map.upper_bound(key); };
204 
206  inline iterator get(const KeyT &key)
207  {
208  iterator mapi = m_map.find(key);
209  if (mapi != m_map.end() && mapi->second != m_list.begin())
210  promote(mapi);
211  return mapi;
212  };
213 
215  void promote(const_iterator &it)
216  { if (it->second != m_list.begin()) m_list.splice(m_list.begin(), m_list, it->second); };
217 
219  void promote(iterator &it)
220  { if (it->second != m_list.begin()) m_list.splice(m_list.begin(), m_list, it->second); };
221 
226  void insert(const KeyT &key, const ValT &val)
227  {
228  iterator mapi = get(key);
229  if (mapi != m_map.end()) {
230  //-- update existing item (it's already been promoted by get() if it exists)
231  mapi->second->second = val;
232  }
233  else if (m_capacity > 0) {
234  //-- insert new item (only if we're not just going to delete it again)
235  m_list.push_front(std::make_pair(key,val));
236  m_map.insert(std::make_pair(key, m_list.begin()));
237  ++m_size;
238  clean();
239  }
240  //-- sanity check: FAILS for NavHintCache on v2.1.10 due to bogus NavHintKey::operator<()
241  //assert(m_size==m_list.size() && m_size==m_map.size());
242  };
243 
244 };
245 
246 
247 #endif /* DDC_LRUCACHE_H */
248 
249 /*--- emacs style variables ---
250  * Local Variables:
251  * mode: C++
252  * c-file-style: "ellemtel"
253  * c-basic-offset: 4
254  * tab-width: 8
255  * indent-tabs-mode: nil
256  * End:
257  */
MapT::iterator iterator
iterator wraps MapT::iterator (~ pair< KeyT, pair<KeyT,ValT>* > *)
Definition: LRUCache.h:75
const_iterator begin() const
Definition: LRUCache.h:175
std::map< KeyT, typename ListT::iterator > MapT
maps keys to lru-list iterators, used to check key existence
Definition: LRUCache.h:72
iterator upper_bound(const KeyT &key)
find upper bound for cache key; does NOT update the MRU-list (non-const)
Definition: LRUCache.h:190
pthread_mutex_t * MutexT
mutex type (pthreads enabled)
Definition: LRUCache.h:59
const_iterator lower_bound(const KeyT &key) const
find lower bound for cache key; does NOT update the MRU-list (const version)
Definition: LRUCache.h:198
iterator lower_bound(const KeyT &key)
find lower bound for cache key; does NOT update the MRU-list (non-const)
Definition: LRUCache.h:186
MapT m_map
maps keys to m_list iterators, used to check key existence
Definition: LRUCache.h:94
std::pair< KeyT, ValT > ItemT
elementary data item: (key,val) pair
Definition: LRUCache.h:66
generic least-recently-used cache template
Definition: LRUCache.h:46
void insert(const KeyT &key, const ValT &val)
Definition: LRUCache.h:226
MutexT mutex() const
get mutex pointer
Definition: LRUCache.h:136
size_t capacity() const
get cache capacity
Definition: LRUCache.h:148
const_iterator find(const KeyT &key) const
find cached item; returns end() if not found; does NOT update the MRU-list (const version) ...
Definition: LRUCache.h:194
ListT m_list
list of (key,val) pairs, position indicates recency of use (most recent first)
Definition: LRUCache.h:91
iterator end()
Definition: LRUCache.h:174
const_iterator upper_bound(const KeyT &key) const
find upper bound for cache key; does NOT update the MRU-list (const version)
Definition: LRUCache.h:202
void lock()
lock the cache mutex, if any
Definition: LRUCache.h:163
#define DDC_DEFAULT_LRU_CACHE_CAPACITY
default cache capacity
Definition: LRUCache.h:41
void clear()
clear all cached items (no implicit locks)
Definition: LRUCache.h:113
void unlock()
unlock cache mutex
Definition: LRUCache.h:167
size_t reserve(size_t cap)
update cache capacity; implicitly calls clean()
Definition: LRUCache.h:152
size_t m_capacity
maximum number of cached items
Definition: LRUCache.h:85
size_t m_size
current number of cached items
Definition: LRUCache.h:88
#define DDC_IFPTHREAD(x)
Definition: LRUCache.h:30
size_t size() const
get number of currently cached items
Definition: LRUCache.h:144
MutexT m_mutex
mutex pointer to use for lock() and unlock() methods
Definition: LRUCache.h:97
MapT::const_iterator const_iterator
const_iterator wraps MapT::const_iterator
Definition: LRUCache.h:78
MutexT mutex(MutexT mut)
set mutex pointer
Definition: LRUCache.h:140
ddcLRUCache(size_t capacity=1024, MutexT mutex=NULL)
default constructor
Definition: LRUCache.h:105
void promote(const_iterator &it)
promote an existing item to the most-recently-used position
Definition: LRUCache.h:215
iterator find(const KeyT &key)
find cached item; returns end() if not found, does NOT update the MRU-list (non-const) ...
Definition: LRUCache.h:182
Key KeyT
key type
Definition: LRUCache.h:52
void promote(iterator &it)
promote an existing item to the most-recently-used position
Definition: LRUCache.h:219
Val ValT
value type
Definition: LRUCache.h:55
iterator begin()
Definition: LRUCache.h:173
std::list< ItemT > ListT
list of (key,val) pairs, position indicates recency of use (most recent first)
Definition: LRUCache.h:69
const_iterator end() const
Definition: LRUCache.h:176
void clean()
drop least recently used cache items until size <= capacity
Definition: LRUCache.h:122