diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-05-01 13:28:43 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-05-08 11:22:08 -0700 |
commit | 5e642fae345f33fd325808922205a6b517b9b4e5 (patch) | |
tree | 43bd377b5cfc9f6bf22b04a8dcf62cdd67159f1c | |
parent | 6659b2b6cf3b231045051cc4654fb3ecfc5d00df (diff) | |
download | ceph-5e642fae345f33fd325808922205a6b517b9b4e5.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.am | 1 | ||||
-rw-r--r-- | src/common/lru_map.h | 94 |
2 files changed, 95 insertions, 0 deletions
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 <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 |