]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
lru_map: infrastructure for a bounded map
authorYehuda Sadeh <yehuda@inktank.com>
Wed, 1 May 2013 20:28:43 +0000 (13:28 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Wed, 8 May 2013 18:22:08 +0000 (11:22 -0700)
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>
src/Makefile.am
src/common/lru_map.h [new file with mode: 0644]

index 523bb8ccccc2ec5497ab85250a623f5691878467..a45dd4e9830876e86de01284cdbfd57fa58b42fb 100644 (file)
@@ -1697,6 +1697,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 (file)
index 0000000..fb63747
--- /dev/null
@@ -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