Skip to content

Instantly share code, notes, and snippets.

@microcai
Created April 9, 2017 10:42
Show Gist options
  • Save microcai/0a3a8abe49b501c931a9acc4b12b0130 to your computer and use it in GitHub Desktop.
Save microcai/0a3a8abe49b501c931a9acc4b12b0130 to your computer and use it in GitHub Desktop.
简单 cache 容器,使用异常处理 cache_miss
#pragma once
#include <tuple>
#include <map>
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
struct cache_miss {};
template<typename KeyType, typename ValueType, int cache_aging_time = 30>
class cache_map
: protected std::map<KeyType, std::tuple<ValueType, boost::posix_time::ptime>>
{
typedef std::map<KeyType, std::tuple<ValueType, boost::posix_time::ptime>> base_type;
public:
ValueType& get_cache(const KeyType& key) throw(cache_miss)
{
boost::shared_lock<boost::shared_mutex> l(m_mutex);
typename base_type::iterator it = base_type::find(key);
if (it == base_type::end())
{
throw cache_miss();
}
std::tuple<ValueType, boost::posix_time::ptime> & value_pack = it->second;
auto should_be_after = boost::posix_time::second_clock::universal_time() - boost::posix_time::seconds(cache_aging_time);
if (std::get<1>(value_pack) > should_be_after)
return std::get<0>(value_pack);
throw cache_miss();
}
const ValueType& get_cache(const KeyType& key) const throw(cache_miss)
{
boost::shared_lock<boost::shared_mutex> l(m_mutex);
typename base_type::const_iterator it = base_type::find(key);
if (it == base_type::end())
{
throw cache_miss();
}
const std::tuple<ValueType, boost::posix_time::ptime> & value_pack = it->second;
auto should_be_after = boost::posix_time::second_clock::universal_time() - boost::posix_time::seconds(cache_aging_time);
if (std::get<1>(value_pack) > should_be_after)
return std::get<0>(value_pack);
throw cache_miss();
}
void add_to_cache(const KeyType& k , const ValueType& v)
{
boost::unique_lock<boost::shared_mutex> l(m_mutex);
base_type::erase(k);
base_type::insert(std::make_pair(k, std::make_tuple(v, boost::posix_time::second_clock::universal_time())));
}
void tick()
{
boost::upgrade_lock<boost::shared_mutex> readlock(m_mutex);
std::shared_ptr<boost::upgrade_to_unique_lock<boost::shared_mutex>> writelock;
auto should_be_after = boost::posix_time::second_clock::universal_time() - boost::posix_time::seconds(30);
for (auto it = base_type::begin(); it != base_type::end(); )
{
const std::tuple<ValueType, boost::posix_time::ptime> & value_pack = it->second;
if (std::get<1>(value_pack) < should_be_after)
{
if (!writelock)
writelock.reset(new boost::upgrade_to_unique_lock<boost::shared_mutex>(readlock));
base_type::erase(it++);
}
else
it++;
}
}
private:
mutable boost::shared_mutex m_mutex;
};
template<typename KeyType, typename ValueType>
class cache_map <KeyType, ValueType, 0>
: protected std::map<KeyType, ValueType>
{
typedef std::map<KeyType, ValueType> base_type;
public:
ValueType& get_cache(const KeyType& key) throw(cache_miss)
{
boost::shared_lock<boost::shared_mutex> l(m_mutex);
auto it = base_type::find(key);
if (it == base_type::end())
{
throw cache_miss();
}
return it->second;
}
void add_to_cache(const KeyType& k , const ValueType& v)
{
boost::unique_lock<boost::shared_mutex> l(m_mutex);
base_type::erase(k);
base_type::insert(std::make_pair(k, v));
}
void tick()
{
}
private:
mutable boost::shared_mutex m_mutex;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment