Created
December 23, 2015 06:43
-
-
Save reyoung/87f230ebc0dfc242ad90 to your computer and use it in GitHub Desktop.
A C++ 11 key-value object instance cache.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <memory> | |
#include <unordered_map> | |
#include <functional> | |
#include <mutex> | |
#include <glog/logging.h> | |
/** | |
* Key-Value Cache Helper. | |
* | |
* It store a object instance global. User can invoke get method by key and a | |
* object creator callback. If there is a instance stored in cache, then it will | |
* return a shared_ptr of it, otherwise, it will invoke creator callback, create | |
* a new instance store global, and return it. | |
* | |
* There are two kind of KVCache, WeakKVCache and StrongKVCache. | |
* In WeakKVCache, the cache instance will release when nobody hold a reference | |
* to it. | |
* In StrongKVCache, the cache instance will never release. | |
* | |
* Use WeakKVCache::Type or StrongKVCache::Type to get these types. (Because | |
* template alias is not implemented in gcc46..) | |
* | |
* The KType is the key type. | |
* The VType is the value type. | |
* The PtrType is either std::shared_ptr<VType> or std::weak_ptr<VType>. Maybe | |
* ThreadLocalPtr in future. | |
* The Hash is the key hasher object. | |
*/ | |
template <typename KType, typename VType, typename PtrType, | |
typename Hash=std::hash<KType>> | |
class KVCache { | |
public: | |
// Interfaces | |
KVCache(); | |
/** | |
* Get Cache Instance. | |
* | |
* @param key: The cache key. | |
* @param creator: The value creator, it will be invoked when there is no | |
* instance store in cache. | |
*/ | |
std::shared_ptr<VType> get(const KType& key, | |
const std::function<VType*()>& creator); | |
}; | |
/** | |
* WeakKVCache implementation. | |
* @see KVCache document. | |
*/ | |
template <typename KType, typename VType, typename Hash> | |
class KVCache<KType, VType, std::weak_ptr<VType>, Hash> { | |
public: | |
KVCache() {} | |
std::shared_ptr<VType> get(const KType& key, | |
const std::function<VType*()>& creator) { | |
std::lock_guard<std::mutex> guard(this->lock_); | |
auto it = this->storage_.find(key); | |
if (it != this->storage_.end()) { | |
auto & val = it->second; | |
auto retVal = val.lock(); | |
if (retVal != nullptr) { | |
return retVal; | |
} // else fall trough. Because it is WeakPtr Cache. | |
} | |
auto rawPtr = creator(); | |
CHECK(rawPtr != nullptr); | |
std::shared_ptr<VType> retVal(rawPtr); | |
this->storage_[key] = retVal; | |
return retVal; | |
} | |
private: | |
std::mutex lock_; | |
std::unordered_map<KType, std::weak_ptr<VType>, Hash> storage_; | |
}; | |
/** | |
* StrongKVCache implementation. | |
* @see KVCache document. | |
*/ | |
template <typename KType, typename VType, typename Hash> | |
class KVCache<KType, VType, std::shared_ptr<VType>, Hash> { | |
public: | |
KVCache() {} | |
std::shared_ptr<VType> get(const KType& key, | |
const std::function<VType*()>& creator) { | |
std::lock_guard<std::mutex> guard(this->lock_); | |
auto it = this->storage_.find(key); | |
if (it != this->storage_.end()) { | |
auto & val = it->second; | |
return val; | |
} else { | |
auto rawPtr = creator(); | |
CHECK(rawPtr != nullptr); | |
std::shared_ptr<VType> retVal(rawPtr); | |
this->storage_[key] = retVal; | |
return retVal; | |
} | |
} | |
private: | |
std::mutex lock_; | |
std::unordered_map<KType, std::shared_ptr<VType>, Hash> storage_; | |
}; | |
template <typename KType, typename VType, typename Hash=std::hash<KType>> | |
class WeakKVCache { // Template alias is supported begin gcc 4.7. | |
public: | |
typedef KVCache<KType, VType, std::weak_ptr<VType>, Hash> Type; | |
}; | |
template <typename KType, typename VType, typename Hash=std::hash<KType>> | |
class StrongKVCache { | |
public: | |
typedef KVCache<KType, VType, std::shared_ptr<VType>, Hash> Type; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment