#pragma once #include "c++11Helpers.h" #include "visibility.h" #include #include #include #include #include #include #include #include #include #include namespace AdHoc { /// @cond template class DLL_PUBLIC Cacheable { public: using Value = const std::shared_ptr; Cacheable(K k, time_t validUntil); SPECIAL_MEMBERS_DEFAULT_MOVE_NO_COPY(Cacheable); virtual ~Cacheable() = default; const K key; const time_t validUntil; [[nodiscard]] virtual Value item() const = 0; }; template class DLL_PUBLIC ObjectCacheable : public Cacheable { public: ObjectCacheable(const T & t, const K & k, time_t validUtil); ObjectCacheable(typename Cacheable::Value t, const K & k, time_t validUtil); [[nodiscard]] typename Cacheable::Value item() const override; private: typename Cacheable::Value value; }; template class DLL_PUBLIC CallCacheable : public Cacheable { public: using Factory = std::function; CallCacheable(const Factory & t, const K & k, time_t validUtil); [[nodiscard]] typename Cacheable::Value item() const override; private: mutable std::variant, Factory> value; mutable std::shared_mutex lock; }; template class DLL_PUBLIC PointerCallCacheable : public Cacheable { public: using Factory = std::function::Value()>; PointerCallCacheable(const Factory & t, const K & k, time_t validUtil); [[nodiscard]] typename Cacheable::Value item() const override; private: mutable std::variant, Factory> value; mutable std::shared_mutex lock; }; struct byValidity { }; struct byKey { }; /// @endcond /// In-memory cache of T, keyed by K. template class DLL_PUBLIC Cache { public: /// @cond using Key = K; using Value = const std::shared_ptr; using Factory = std::function; using PointerFactory = std::function; using Item = Cacheable; using Element = std::shared_ptr; /// @endcond /** Construct a default empty cache. */ Cache(); /** Add a known item to the cache. * @param k The key of the cache item. * @param t The item to cache. * @param validUntil The absolute time the cache item should expire. */ void add(const K & k, const T & t, time_t validUntil); /** Add a known item to the cache. * @param k The key of the cache item. * @param t The item to cache. * @param validUntil The absolute time the cache item should expire. */ void addPointer(const K & k, Value & t, time_t validUntil); /** Add a callback item to the cache. * The callback will be called on first hit of the cache item, at which * point the return value of the function will be cached. * @param k The key of the cache item. * @param tf The callback function to cache. * @param validUntil The absolute time the cache item should expire. */ void addFactory(const K & k, const Factory & tf, time_t validUntil); /** Add a pointer callback item to the cache. * The callback will be called on first hit of the cache item, at which * point the return value of the function will be cached. * @param k The key of the cache item. * @param tf The callback function to cache. * @param validUntil The absolute time the cache item should expire. */ void addPointerFactory(const K & k, const PointerFactory & tf, time_t validUntil); /** Get an Element from the cache. The element represents the key, item and expiry time. * Returns null on cache-miss. * @param k Cache key to get. */ Element getItem(const K & k) const; /** Get an Item from the cache. Returns null on cache-miss. * @param k Cache key to get. */ Value get(const K & k) const; /** Get the size of the cache (number of items). @warning This cannot be reliably used to * determine or estimate the amount of memory used by items in the cache without further * knowledge of the items themselves. */ size_t size() const; /** Explicitly remove an item from the cache. * @param k Cache key to remove. */ void remove(const K & k); /** Explicitly remove ALL items from the cache. */ void clear(); private: void DLL_PRIVATE prune() const; mutable time_t lastPruneTime; mutable std::shared_mutex lock; using Cached = boost::multi_index::multi_index_container, BOOST_MULTI_INDEX_MEMBER(Item, const K, key)>, boost::multi_index::ordered_non_unique, BOOST_MULTI_INDEX_MEMBER(Item, const time_t, validUntil)>>>; mutable Cached cached; }; }