X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fcommon%2Flru_map.h;fp=src%2Fceph%2Fsrc%2Fcommon%2Flru_map.h;h=35722fcd08ab1e14fe77f0f11b31691b50606a38;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/common/lru_map.h b/src/ceph/src/common/lru_map.h new file mode 100644 index 0000000..35722fc --- /dev/null +++ b/src/ceph/src/common/lru_map.h @@ -0,0 +1,132 @@ +#ifndef CEPH_LRU_MAP_H +#define CEPH_LRU_MAP_H + +#include "common/Mutex.h" + +template +class lru_map { + struct entry { + V value; + typename std::list::iterator lru_iter; + }; + + std::map entries; + std::list entries_lru; + + Mutex lock; + + size_t max; + +public: + class UpdateContext { + public: + virtual ~UpdateContext() {} + + /* update should return true if object is updated */ + virtual bool update(V *v) = 0; + }; + + bool _find(const K& key, V *value, UpdateContext *ctx); + void _add(const K& key, V& value); + +public: + lru_map(int _max) : lock("lru_map"), max(_max) {} + virtual ~lru_map() {} + + bool find(const K& key, V& value); + + /* + * find_and_update() + * + * - will return true if object is found + * - if ctx is set will return true if object is found and updated + */ + bool find_and_update(const K& key, V *value, UpdateContext *ctx); + void add(const K& key, V& value); + void erase(const K& key); +}; + +template +bool lru_map::_find(const K& key, V *value, UpdateContext *ctx) +{ + typename std::map::iterator iter = entries.find(key); + if (iter == entries.end()) { + return false; + } + + entry& e = iter->second; + entries_lru.erase(e.lru_iter); + + bool r = true; + + if (ctx) + r = ctx->update(&e.value); + + if (value) + *value = e.value; + + entries_lru.push_front(key); + e.lru_iter = entries_lru.begin(); + + return r; +} + +template +bool lru_map::find(const K& key, V& value) +{ + Mutex::Locker l(lock); + return _find(key, &value, NULL); +} + +template +bool lru_map::find_and_update(const K& key, V *value, UpdateContext *ctx) +{ + Mutex::Locker l(lock); + return _find(key, value, ctx); +} + +template +void lru_map::_add(const K& key, V& value) +{ + typename std::map::iterator iter = entries.find(key); + if (iter != entries.end()) { + entry& e = iter->second; + entries_lru.erase(e.lru_iter); + } + + entries_lru.push_front(key); + entry& e = entries[key]; + e.value = value; + e.lru_iter = entries_lru.begin(); + + while (entries.size() > max) { + typename std::list::reverse_iterator riter = entries_lru.rbegin(); + iter = entries.find(*riter); + // assert(iter != entries.end()); + entries.erase(iter); + entries_lru.pop_back(); + } +} + + +template +void lru_map::add(const K& key, V& value) +{ + Mutex::Locker l(lock); + _add(key, value); +} + +template +void lru_map::erase(const K& key) +{ + Mutex::Locker l(lock); + typename std::map::iterator iter = entries.find(key); + if (iter == entries.end()) + return; + + entry& e = iter->second; + entries_lru.erase(e.lru_iter); + entries.erase(iter); +} + +#endif