Commit 18c95e67 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

cache with concurrent access policies added

parent a6593546
Pipeline #1127 passed with stage
in 3 minutes and 9 seconds
......@@ -3,12 +3,38 @@
#include <tuple>
#include <type_traits>
#include <dune/common/hash.hh>
#include <amdis/common/IndexSeq.hpp>
#include <amdis/common/Mpl.hpp>
#include <amdis/common/Utility.hpp>
namespace AMDiS
{
namespace Impl
{
// Recursive template code derived from Matthieu M.
template <class Tuple, std::size_t I = std::tuple_size<Tuple>::value - 1>
struct HashTupleImpl
{
static void apply(size_t& seed, Tuple const& tuple)
{
HashTupleImpl<Tuple, I-1>::apply(seed, tuple);
Dune::hash_combine(seed, std::get<I>(tuple));
}
};
template <class Tuple>
struct HashTupleImpl<Tuple, 0>
{
static void apply(std::size_t& seed, Tuple const& tuple)
{
Dune::hash_combine(seed, std::get<0>(tuple));
}
};
} // end namespace Impl
namespace Impl
{
template <class Tuple, std::size_t N>
......
#pragma once
#include <mutex>
#include <thread>
#include <tuple>
#include <unordered_map>
#include <amdis/common/Concepts.hpp>
namespace AMDiS
{
namespace tag
{
struct thread_local_policy {};
struct shared_policy {};
}
template <class Key,
class Data,
class Policy = tag::thread_local_policy>
class ConcurrentCache
{
using key_type = Key;
using data_type = Data;
public:
/// Return the data associated to the key. If not yet initialized, call functor f
template <class F,
REQUIRES(Concepts::Callable<F,data_type*,key_type>)>
static data_type const& get(key_type key, F&& f)
{
return instance(Policy{}).get_or_init(key, std::forward<F>(f));
}
private:
auto& guarded_get(key_type const& key, tag::shared_policy)
{
std::lock_guard<std::mutex> lock(access_mutex);
return cached_data[key];
}
auto& guarded_get(key_type const& key, tag::thread_local_policy)
{
return cached_data[key];
}
template <class F>
data_type const& get_or_init(key_type const& key, F&& f)
{
auto& data = guarded_get(key, Policy{});
std::call_once(data.first, std::forward<F>(f), &data.second, key);
return data.second;
}
private:
// Return an instance of this class with static storage
static ConcurrentCache& instance(tag::shared_policy)
{
static ConcurrentCache cache;
return cache;
}
// Return an instance of this class with thread_local storage
static ConcurrentCache& instance(tag::thread_local_policy)
{
thread_local ConcurrentCache cache;
return cache;
}
// private constructor
ConcurrentCache() = default;
// mutex used to access the data in the container, necessary since
// access by operator[] is read+write access, i.e. an empty data element
// is created if it does not exist yet.
std::mutex access_mutex;
// Container to store the cached values
std::unordered_map<key_type, std::pair<std::once_flag, data_type>> cached_data;
};
} // end namespace AMDiS
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment