summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-05-01 13:28:43 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-05-01 13:33:33 -0700
commit7c56039aebc4f21a6498cdb2f3ccdcc3319ed292 (patch)
treec0229ea48fec293f066eb64357804e1c0ec0097f
parentfc48937cdcf9adc6cde7d7d17022741efa93787f (diff)
downloadceph-7c56039aebc4f21a6498cdb2f3ccdcc3319ed292.tar.gz
lru_map: infrastructure for a bounded map
Useful for cache-like maps, where we want to control the max number of entries in the map. Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r--src/Makefile.am1
-rw-r--r--src/common/lru_map.h94
2 files changed, 95 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b8d2c3c3d88..123b474a9e4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1679,6 +1679,7 @@ noinst_HEADERS = \
common/ceph_crypto.h\
common/ceph_crypto_cms.h\
common/ceph_json.h\
+ common/lru_map.h\
common/utf8.h\
common/mime.h\
common/pick_address.h\
diff --git a/src/common/lru_map.h b/src/common/lru_map.h
new file mode 100644
index 00000000000..fb637478884
--- /dev/null
+++ b/src/common/lru_map.h
@@ -0,0 +1,94 @@
+#ifndef CEPH_LRU_MAP_H
+#define CEPH_LRU_MAP_H
+
+#include <list>
+#include <map>
+#include "common/Mutex.h"
+
+
+template <class K, class V>
+class lru_map {
+ struct entry {
+ V value;
+ typename std::list<K>::iterator lru_iter;
+ };
+
+ std::map<K, entry> tokens;
+ std::list<K> tokens_lru;
+
+ Mutex lock;
+
+ size_t max;
+
+public:
+ lru_map(int _max) : lock("lru_map"), max(_max) {}
+ virtual ~lru_map() {}
+
+ bool find(const K& key, V& value);
+ void add(const K& key, V& value);
+ void erase(const K& key);
+};
+
+template <class K, class V>
+bool lru_map<K, V>::find(const K& key, V& value)
+{
+ lock.Lock();
+ typename std::map<K, entry>::iterator iter = tokens.find(key);
+ if (iter == tokens.end()) {
+ lock.Unlock();
+ return false;
+ }
+
+ entry& e = iter->second;
+ tokens_lru.erase(e.lru_iter);
+
+ value = e.value;
+
+ tokens_lru.push_front(key);
+ e.lru_iter = tokens_lru.begin();
+
+ lock.Unlock();
+
+ return true;
+}
+
+template <class K, class V>
+void lru_map<K, V>::add(const K& key, V& value)
+{
+ lock.Lock();
+ typename std::map<K, entry>::iterator iter = tokens.find(key);
+ if (iter != tokens.end()) {
+ entry& e = iter->second;
+ tokens_lru.erase(e.lru_iter);
+ }
+
+ tokens_lru.push_front(key);
+ entry& e = tokens[key];
+ e.value = value;
+ e.lru_iter = tokens_lru.begin();
+
+ while (tokens_lru.size() > max) {
+ typename std::list<K>::reverse_iterator riter = tokens_lru.rbegin();
+ iter = tokens.find(*riter);
+ // assert(iter != tokens.end());
+ tokens.erase(iter);
+ tokens_lru.pop_back();
+ }
+
+ lock.Unlock();
+}
+
+template <class K, class V>
+void lru_map<K, V>::erase(const K& key)
+{
+ Mutex::Locker l(lock);
+ typename std::map<K, entry>::iterator iter = tokens.find(key);
+ if (iter == tokens.end())
+ return;
+
+ entry& e = iter->second;
+ tokens_lru.erase(e.lru_iter);
+ tokens.erase(iter);
+}
+
+#endif