20class ExpirableContainer {
22 explicit ExpirableContainer(size_t max_size, std::chrono::milliseconds ttl)
23 : container_(max_size),
26 UINVARIANT(ttl.count() > 0,
"ttl must be positive");
27 UINVARIANT(max_size > 0,
"capacity must be positive");
30 template <
typename... Args>
31 auto emplace(Args&&... args) {
33 auto result = container_.emplace(now, std::forward<Args>(args)...);
36 result.first->last_accessed = now;
42 bool insert(
const Value& value) {
return emplace(value).second; }
44 bool insert(Value&& value) {
return emplace(std::move(value)).second; }
46 template <
typename Tag,
typename Key>
47 auto find(
const Key& key) {
49 auto it = container_.
template find<Tag, Key>(key);
51 if (it != container_.
template end<Tag>()) {
52 if (now > it->last_accessed + ttl_) {
56 it->last_accessed = now;
60 return impl::IteratorToValue{it};
63 template <
typename Tag,
typename Key>
64 auto find_no_update(
const Key& key)
const {
65 auto it = container_.
template find_no_update<Tag, Key>(key);
66 return impl::IteratorToValue{it};
69 template <
typename Tag,
typename Key>
70 auto equal_range(
const Key& key) {
72 auto range = container_.
template equal_range<Tag, Key>(key);
74 auto it = range.first;
77 while (it != range.second) {
78 if (now > it->last_accessed + ttl_) {
79 it = container_.erase(it);
82 it->last_accessed = now;
87 range = container_.
template equal_range_no_update<Tag, Key>(key);
89 return std::pair{impl::IteratorToValue{range.first}, impl::IteratorToValue{range.second}};
92 template <
typename Tag,
typename Key>
93 auto equal_range_no_update(
const Key& key)
const {
94 auto [begin, end] = container_.
template equal_range_no_update<Tag, Key>(key);
95 return std::pair{impl::IteratorToValue{begin}, impl::IteratorToValue{end}};
98 template <
typename Tag,
typename Key>
99 bool contains(
const Key& key) {
100 return this->
template find<Tag, Key>(key) !=
this->
template end<Tag>();
103 template <
typename Tag,
typename Key>
104 bool contains_no_update(
const Key& key)
const {
105 return this->
template find_no_update<Tag, Key>(key) !=
this->
template end<Tag>();
110 template <
typename IteratorType>
112 return container_.erase(it);
117 template <
typename Tag,
typename Key>
119 return container_.
template erase<Tag, Key>(key);
122 std::size_t size()
const noexcept {
return container_.size(); }
124 bool empty()
const noexcept {
return container_.empty(); }
126 std::size_t capacity()
const noexcept {
return container_.capacity(); }
128 void set_capacity(std::size_t new_capacity) { container_.set_capacity(new_capacity); }
135 void clear() { container_.clear(); }
137 template <
typename Tag>
139 return impl::IteratorToValue{container_.
template end<Tag>()};
146 while (!container_.empty()) {
147 const auto it = container_.find_last_accessed_no_update();
148 if (now > it->last_accessed + ttl_) {
149 container_.erase(it);
157 using CacheItem = impl::TimestampedValue<Value>;
158 using CacheContainer =
Container<CacheItem, IndexSpecifierList, Allocator>;
160 CacheContainer container_;
161 std::chrono::milliseconds ttl_;