From: Yehuda Sadeh Date: Wed, 1 May 2013 20:28:43 +0000 (-0700) Subject: lru_map: infrastructure for a bounded map X-Git-Tag: v0.67-rc1~128^2~147 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5e642fae345f33fd325808922205a6b517b9b4e5;p=ceph.git 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 --- diff --git a/src/Makefile.am b/src/Makefile.am index 523bb8ccccc..a45dd4e9830 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 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 +#include +#include "common/Mutex.h" + + +template +class lru_map { + struct entry { + V value; + typename std::list::iterator lru_iter; + }; + + std::map tokens; + std::list 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 +bool lru_map::find(const K& key, V& value) +{ + lock.Lock(); + typename std::map::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 +void lru_map::add(const K& key, V& value) +{ + lock.Lock(); + typename std::map::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::reverse_iterator riter = tokens_lru.rbegin(); + iter = tokens.find(*riter); + // assert(iter != tokens.end()); + tokens.erase(iter); + tokens_lru.pop_back(); + } + + lock.Unlock(); +} + +template +void lru_map::erase(const K& key) +{ + Mutex::Locker l(lock); + typename std::map::iterator iter = tokens.find(key); + if (iter == tokens.end()) + return; + + entry& e = iter->second; + tokens_lru.erase(e.lru_iter); + tokens.erase(iter); +} + +#endif