Commit b356d05e authored by Müller, Felix's avatar Müller, Felix

Added local (instance) storage option to ConcurrentCache

parent 32e77c49
Pipeline #1693 failed with stage
in 162 minutes and 34 seconds
......@@ -78,7 +78,8 @@ namespace AMDiS
static GridTransferInterface* gridTransferInterface(Grid const &grid)
{
Key key = Key(&grid);
auto& gridTransferInterfaceUniquePtr = GridTransferCache::get(key, [&](Key const&)
GridTransferCache cache;
auto& gridTransferInterfaceUniquePtr = cache.get(key, [&](Key const&)
{
return std::make_unique<GridTransfer<Grid>>();
});
......
......@@ -11,6 +11,10 @@
namespace AMDiS
{
/// Store cache in instance.
template <class Container>
struct ConsecutivePolicy;
/// Store cache thread local, requires no locking.
template <class Container>
struct ThreadLocalPolicy;
......@@ -29,9 +33,10 @@ namespace AMDiS
* \tparam Key The type of key to access the data.
* \tparam Data The type of the data stored in the cache. The behaviur is undefined if Data is not
* the same type as Container::mapped_type.
* \tparam Policy A policy class template implementing the method `get_or_init()`. Two implementations
* are provided: \ref ThreadLocalPolicy and \ref StaticLockedPolicy. By default, if not
* Policy class template is specified, the `ThreadLocalPolicy` is used. \see ConcurrentCachePolicy
* \tparam Policy A policy class template implementing the method `get_or_init()`. Three implementations
* are provided: \ref ConsecutivePolicy, \ref ThreadLocalPolicy and \ref StaticLockedPolicy.
* By default, if no policy class template is specified, the `ThreadLocalPolicy` is used.
* \see ConcurrentCachePolicy
* \tparam Container The type of the underlying associative container to use to store the data. The
* container must satisfy the requirements of AssociativeContainer. The standard
* containers `std::map` and `std::unordered_map` satisfie this requirement. By default,
......@@ -54,7 +59,7 @@ namespace AMDiS
* Provide a static cache and a `get_or_init()` static method that extracts the data from the cache if it exists or
* creates a new extry by using an initialization functor.
*
* Realizations of this template are \ref ThreadLocalPolicy and \ref StaticLockedPolicy.
* Realizations of this template are \ref ConsecutivePolicy, \ref ThreadLocalPolicy and \ref StaticLockedPolicy.
*
* \tparam Container The Type of the associative container key->data to store the cached data.
**/
......@@ -62,7 +67,54 @@ namespace AMDiS
class ConcurrentCachePolicy;
#endif
// implementation of the ThreadLocal policy
// implementation of the consecutive policy. Data is stored in instance variable.
template <class Container>
struct ConsecutivePolicy
{
using key_type = typename Container::key_type;
using data_type = typename Container::mapped_type;
using container_type = Container;
template <class F, class... Args>
data_type const& get_or_init(key_type const& key, F&& f, Args&&... args) const
{
return impl(std::is_default_constructible<data_type>{},
key, std::forward<F>(f), std::forward<Args>(args)...);
}
private:
// data_type is default_constructible
template <class F, class... Args>
data_type const& impl(std::true_type, key_type const& key, F&& f, Args&&... args) const
{
data_type empty;
auto it = cachedData_.emplace(key, std::move(empty));
if (it.second) {
data_type data = f(key, std::forward<Args>(args)...);
it.first->second = std::move(data);
}
return it.first->second;
}
// data_type is not default_constructible
template <class F, class... Args>
data_type const& impl(std::false_type, key_type const& key, F&& f, Args&&... args) const
{
auto it = cachedData_.find(key);
if (it != cachedData_.end())
return it->second;
else {
data_type data = f(key, std::forward<Args>(args)...);
auto it = cachedData_.emplace(key, std::move(data));
return it.first->second;
}
}
mutable container_type cachedData_;
};
// implementation of the ThreadLocal policy. Data is stored in thread_local variable.
template <class Container>
struct ThreadLocalPolicy
{
......@@ -113,7 +165,7 @@ namespace AMDiS
};
// implementation of the Shared policy
// implementation of the Shared policy. Data is stored in static variable.
template <class Container>
struct StaticLockedPolicy
{
......@@ -151,7 +203,7 @@ namespace AMDiS
template <class Key, class Data, template <class> class Policy, class Container>
class ConcurrentCache
: private Policy<Container>
: protected Policy<Container>
{
using key_type = Key;
using data_type = Data;
......@@ -167,7 +219,7 @@ namespace AMDiS
* \param args... Arguments passed additionally to the functor f
**/
template <class F, class... Args>
static data_type const& get(key_type const& key, F&& f, Args&&... args)
data_type const& get(key_type const& key, F&& f, Args&&... args) const
{
static_assert(Dune::Std::is_callable<F(key_type, Args...), data_type>::value,
"Functor F must have the signature data_type(key_type, Args...)");
......
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