431a9c00a5
On Linux and macOS, using Clang to compile OpenStarbound produces about 400 MB worth of warnings during the build, making the compiler output unreadable and slowing the build down considerably. 99% of the warnings were unqualified uses of std::move and std::forward, which are now all properly qualified. Fixed a few other minor warnings about non-virtual destructors and some uses of std::move preventing copy elision on temporary objects. Most remaining warnings are now unused parameters.
204 lines
6.2 KiB
C++
204 lines
6.2 KiB
C++
#ifndef STAR_TTL_CACHE_HPP
|
|
#define STAR_TTL_CACHE_HPP
|
|
|
|
#include "StarLruCache.hpp"
|
|
#include "StarTime.hpp"
|
|
#include "StarRandom.hpp"
|
|
|
|
namespace Star {
|
|
|
|
template <typename LruCacheType>
|
|
class TtlCacheBase {
|
|
public:
|
|
typedef typename LruCacheType::Key Key;
|
|
typedef typename LruCacheType::Value::second_type Value;
|
|
|
|
typedef function<Value(Key const&)> ProducerFunction;
|
|
|
|
TtlCacheBase(int64_t timeToLive = 10000, int timeSmear = 1000, size_t maxSize = NPos, bool ttlUpdateEnabled = true);
|
|
|
|
int64_t timeToLive() const;
|
|
void setTimeToLive(int64_t timeToLive);
|
|
|
|
int timeSmear() const;
|
|
void setTimeSmear(int timeSmear);
|
|
|
|
// If a max size is set, this cache also acts as an LRU cache with the given
|
|
// maximum size.
|
|
size_t maxSize() const;
|
|
void setMaxSize(size_t maxSize = NPos);
|
|
|
|
size_t currentSize() const;
|
|
|
|
List<Key> keys() const;
|
|
List<Value> values() const;
|
|
|
|
// If ttlUpdateEnabled is false, then the time to live for entries will not
|
|
// be updated on access.
|
|
bool ttlUpdateEnabled() const;
|
|
void setTtlUpdateEnabled(bool enabled);
|
|
|
|
// If the value is in the cache, returns it and updates the access time,
|
|
// otherwise returns nullptr.
|
|
Value* ptr(Key const& key);
|
|
|
|
// Put the given value into the cache.
|
|
void set(Key const& key, Value value);
|
|
// Removes the given value from the cache. If found and removed, returns
|
|
// true.
|
|
bool remove(Key const& key);
|
|
|
|
// Remove all key / value pairs matching a filter.
|
|
void removeWhere(function<bool(Key const&, Value&)> filter);
|
|
|
|
// If the value for the key is not found in the cache, produce it with the
|
|
// given producer. Producer should take the key as an argument and return
|
|
// the Value.
|
|
template <typename Producer>
|
|
Value& get(Key const& key, Producer producer);
|
|
|
|
void clear();
|
|
|
|
// Cleanup any cached entries that are older than their time to live, if the
|
|
// refreshFilter is given, things that match the refreshFilter instead have
|
|
// their ttl refreshed rather than being removed.
|
|
void cleanup(function<bool(Key const&, Value const&)> refreshFilter = {});
|
|
|
|
private:
|
|
LruCacheType m_cache;
|
|
int64_t m_timeToLive;
|
|
int m_timeSmear;
|
|
bool m_ttlUpdateEnabled;
|
|
};
|
|
|
|
template <typename Key, typename Value, typename Compare = std::less<Key>, typename Allocator = BlockAllocator<pair<Key const, pair<int64_t, Value>>, 1024>>
|
|
using TtlCache = TtlCacheBase<LruCache<Key, pair<int64_t, Value>, Compare, Allocator>>;
|
|
|
|
template <typename Key, typename Value, typename Hash = Star::hash<Key>, typename Equals = std::equal_to<Key>, typename Allocator = BlockAllocator<pair<Key const, pair<int64_t, Value>>, 1024>>
|
|
using HashTtlCache = TtlCacheBase<HashLruCache<Key, pair<int64_t, Value>, Hash, Equals, Allocator>>;
|
|
|
|
template <typename LruCacheType>
|
|
TtlCacheBase<LruCacheType>::TtlCacheBase(int64_t timeToLive, int timeSmear, size_t maxSize, bool ttlUpdateEnabled) {
|
|
m_cache.setMaxSize(maxSize);
|
|
m_timeToLive = timeToLive;
|
|
m_timeSmear = timeSmear;
|
|
m_ttlUpdateEnabled = ttlUpdateEnabled;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
int64_t TtlCacheBase<LruCacheType>::timeToLive() const {
|
|
return m_timeToLive;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::setTimeToLive(int64_t timeToLive) {
|
|
m_timeToLive = timeToLive;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
int TtlCacheBase<LruCacheType>::timeSmear() const {
|
|
return m_timeSmear;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::setTimeSmear(int timeSmear) {
|
|
m_timeSmear = timeSmear;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
bool TtlCacheBase<LruCacheType>::ttlUpdateEnabled() const {
|
|
return m_ttlUpdateEnabled;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
size_t TtlCacheBase<LruCacheType>::maxSize() const {
|
|
return m_cache.maxSize();
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::setMaxSize(size_t maxSize) {
|
|
m_cache.setMaxSize(maxSize);
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
size_t TtlCacheBase<LruCacheType>::currentSize() const {
|
|
return m_cache.currentSize();
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
auto TtlCacheBase<LruCacheType>::keys() const -> List<Key> {
|
|
return m_cache.keys();
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
auto TtlCacheBase<LruCacheType>::values() const -> List<Value> {
|
|
List<Value> values;
|
|
for (auto& p : m_cache.values())
|
|
values.append(std::move(p.second));
|
|
return values;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::setTtlUpdateEnabled(bool enabled) {
|
|
m_ttlUpdateEnabled = enabled;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
auto TtlCacheBase<LruCacheType>::ptr(Key const& key) -> Value * {
|
|
if (auto p = m_cache.ptr(key)) {
|
|
if (m_ttlUpdateEnabled)
|
|
p->first = Time::monotonicMilliseconds() + Random::randInt(-m_timeSmear, m_timeSmear);
|
|
return &p->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::set(Key const& key, Value value) {
|
|
m_cache.set(key, make_pair(Time::monotonicMilliseconds() + Random::randInt(-m_timeSmear, m_timeSmear), value));
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
bool TtlCacheBase<LruCacheType>::remove(Key const& key) {
|
|
return m_cache.remove(key);
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::removeWhere(function<bool(Key const&, Value&)> filter) {
|
|
m_cache.removeWhere([&filter](auto const& key, auto& value) { return filter(key, value.second); });
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
template <typename Producer>
|
|
auto TtlCacheBase<LruCacheType>::get(Key const& key, Producer producer) -> Value & {
|
|
auto& value = m_cache.get(key, [producer](Key const& key) {
|
|
return pair<int64_t, Value>(0, producer(key));
|
|
});
|
|
if (value.first == 0 || m_ttlUpdateEnabled)
|
|
value.first = Time::monotonicMilliseconds() + Random::randInt(-m_timeSmear, m_timeSmear);
|
|
return value.second;
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::clear() {
|
|
m_cache.clear();
|
|
}
|
|
|
|
template <typename LruCacheType>
|
|
void TtlCacheBase<LruCacheType>::cleanup(function<bool(Key const&, Value const&)> refreshFilter) {
|
|
int64_t currentTime = Time::monotonicMilliseconds();
|
|
m_cache.removeWhere([&](auto const& key, auto& value) {
|
|
if (refreshFilter && refreshFilter(key, value.second)) {
|
|
value.first = currentTime;
|
|
} else {
|
|
if (currentTime - value.first > m_timeToLive)
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|