| |
| |
| |
| |
|
|
| #pragma once |
|
|
| #include <aws/core/utils/DateTime.h> |
| #include <aws/core/utils/memory/stl/AWSMap.h> |
| #include <chrono> |
|
|
| namespace Aws |
| { |
| namespace Utils |
| { |
| |
| |
| |
| template <typename TKey, typename TValue> |
| class Cache |
| { |
| public: |
| |
| |
| |
| |
| explicit Cache(size_t initialSize = 1000) : m_maxSize(initialSize) |
| { |
| } |
|
|
| struct Value |
| { |
| DateTime expiration; |
| TValue val; |
| }; |
|
|
| |
| |
| |
| |
| |
| bool Get(const TKey& key, TValue& value) const |
| { |
| auto it = m_entries.find(key); |
| if (it == m_entries.end()) |
| { |
| return false; |
| } |
|
|
| if (DateTime::Now() > it->second.expiration) |
| { |
| return false; |
| } |
|
|
| value = it->second.val; |
| return true; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| template<typename UValue> |
| void Put(TKey&& key, UValue&& val, std::chrono::milliseconds duration) |
| { |
| auto it = m_entries.find(key); |
| const DateTime expiration = DateTime::Now() + duration; |
| if (it != m_entries.end()) |
| { |
| it->second.val = std::forward<UValue>(val); |
| it->second.expiration = expiration; |
| return; |
| } |
|
|
| if (m_entries.size() >= m_maxSize) |
| { |
| Prune(); |
| } |
|
|
| m_entries.emplace(std::move(key), Value { expiration, std::forward<UValue>(val) }); |
| } |
|
|
| template<typename UValue> |
| void Put(const TKey& key, UValue&& val, std::chrono::milliseconds duration) |
| { |
| auto it = m_entries.find(key); |
| const DateTime expiration = DateTime::Now() + duration; |
| if (it != m_entries.end()) |
| { |
| it->second.val = std::forward<UValue>(val); |
| it->second.expiration = expiration; |
| return; |
| } |
|
|
| if (m_entries.size() >= m_maxSize) |
| { |
| Prune(); |
| } |
|
|
| m_entries.emplace(key, Value { expiration, std::forward<UValue>(val) }); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| using TransformFunction = std::function<Value(const TKey &, Value &)>; |
| void Transform(TransformFunction function) { |
| for (auto it = m_entries.begin(); it != m_entries.end(); ++it) { |
| it->second = function(it->first, it->second); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| using FilterFunction = std::function<bool(const TKey &, const Value&)>; |
| void Filter(FilterFunction function) { |
| auto it = m_entries.begin(); |
| while (it != m_entries.end()) { |
| auto shouldFilter = function(it->first, it->second); |
| if (shouldFilter) { |
| it = m_entries.erase(it); |
| } else { |
| ++it; |
| } |
| } |
| } |
|
|
| private: |
|
|
| void Prune() |
| { |
| auto mostExpiring = m_entries.begin(); |
| |
| for (auto it = m_entries.begin(); it != m_entries.end();) |
| { |
| if (DateTime::Now() > it->second.expiration) |
| { |
| it = m_entries.erase(it); |
| } |
| else |
| { |
| if (it->second.expiration < mostExpiring->second.expiration) |
| { |
| mostExpiring = it; |
| } |
| ++it; |
| } |
| } |
|
|
| |
| if (m_entries.size() >= m_maxSize) |
| { |
| m_entries.erase(mostExpiring); |
| } |
| } |
|
|
| Aws::Map<TKey, Value> m_entries; |
| const size_t m_maxSize; |
| }; |
| } |
| } |
|
|