LibQuicR
Loading...
Searching...
No Matches
cache.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) 2024 Cisco Systems
2// SPDX-License-Identifier: BSD-2-Clause
3
4#pragma once
5
6#include <atomic>
7#include <chrono>
8#include <map>
9#include <memory>
10#include <stdexcept>
11#include <vector>
12
13#include "detail/tick_service.h"
14
15namespace quicr {
16 template<typename K, typename T>
17 class Cache
18 {
19 /*=======================================================================*/
20 // Internal type definitions
21 /*=======================================================================*/
22
23 using TickType = TickService::TickType;
24 using IndexType = std::uint32_t;
25
26 using BucketType = std::vector<K>;
27 using ValueType = std::shared_ptr<T>;
28 using CacheType = std::map<K, ValueType>;
29
30 public:
31 Cache(size_t duration, size_t interval, std::shared_ptr<TickService> tick_service)
32 : duration_{ duration }
33 , interval_{ interval }
35 , tick_service_(std::move(tick_service))
36 {
37 if (duration == 0 || duration % interval != 0 || duration == interval) {
38 throw std::invalid_argument("Invalid time_queue constructor args");
39 }
40
41 if (!tick_service_) {
42 throw std::invalid_argument("Tick service cannot be null");
43 }
44
46 }
47
48 Cache() = delete;
49 Cache(const Cache&) = default;
50 Cache(Cache&&) noexcept = default;
51
52 Cache& operator=(const Cache&) = default;
53 Cache& operator=(Cache&&) noexcept = default;
54
55 size_t Size() const noexcept { return cache_.size(); }
56 bool Empty() const noexcept { return cache_.empty(); }
57
58 void Insert(const K& key, const T& value, size_t ttl) { InternalInsert(key, value, ttl); }
59
60 void Insert(const K& key, T&& value, size_t ttl) { InternalInsert(key, std::move(value), ttl); }
61
62 bool Contains(const K& key) noexcept
63 {
64 Advance();
65 return cache_.find(key) != cache_.end();
66 }
67
68 bool Contains(const K& start_key, const K& end_key)
69 {
70 if (start_key >= end_key) {
71 throw std::invalid_argument("Exclusive end key must be greater than start key");
72 }
73
74 Advance();
75
76 for (auto key = start_key; key < end_key; ++key) {
77 if (cache_.find(key) == cache_.end()) {
78 return false;
79 }
80 }
81
82 return true;
83 }
84
85 ValueType Get(const K& key) noexcept
86 {
87 if (!Contains(key)) {
88 return nullptr;
89 }
90
91 return cache_.at(key);
92 }
93
94 std::vector<ValueType> Get(const K& start_key, const K& end_key)
95 {
96
97 if (!Contains(start_key, end_key)) {
98 return {};
99 }
100
101 std::vector<ValueType> entries(end_key - start_key, nullptr);
102 for (auto key = start_key; key < end_key; ++key) {
103 entries[key - start_key] = cache_.at(key);
104 }
105
106 return entries;
107 }
108
109 ValueType First() noexcept
110 {
111 Advance();
112
113 if (cache_.empty()) {
114 return nullptr;
115 }
116
117 return std::begin(cache_)->second;
118 }
119
120 ValueType Last() noexcept
121 {
122 Advance();
123
124 if (cache_.empty()) {
125 return nullptr;
126 }
127
128 return std::prev(std::end(cache_))->second;
129 }
130
131 void Clear() noexcept
132 {
133 cache_.clear();
134 bucket_index_ = 0;
135
136 for (auto& bucket : buckets_) {
137 bucket.clear();
138 }
139 }
140
141 protected:
142 inline void Advance()
143 {
144 const TickType new_ticks = tick_service_->Milliseconds();
145 const TickType delta = current_ticks_ ? (new_ticks - current_ticks_) / interval_ : 0;
146 current_ticks_ = new_ticks;
147
148 if (delta == 0) {
149 return;
150 }
151
152 if (delta >= static_cast<TickType>(total_buckets_)) {
153 Clear();
154 return;
155 }
156
157 for (TickType i = 0; i < delta; ++i) {
158 auto& bucket = buckets_[(bucket_index_ + i) % total_buckets_];
159 for (const auto& key : bucket) {
160 cache_.erase(key);
161 }
162 bucket.clear();
163 }
164
166 }
167
168 template<typename Value>
169 inline void InternalInsert(const K& key, Value value, size_t ttl)
170 {
171 if (ttl > duration_) {
172 throw std::invalid_argument("TTL is greater than max duration");
173 } else if (ttl == 0) {
174 ttl = duration_;
175 }
176
177 ttl /= interval_;
178
179 Advance();
180 const IndexType future_index = (bucket_index_ + ttl - 1) % total_buckets_;
181
182 buckets_[future_index].push_back(key);
183 cache_[key] = std::make_shared<T>(value);
184 }
185
186 protected:
188 const size_t duration_;
189
191 const size_t interval_;
192
194 const size_t total_buckets_;
195
197 IndexType bucket_index_{ 0 };
198
200 TickType current_ticks_{ 0 };
201
203 std::vector<BucketType> buckets_;
204
206 CacheType cache_;
207
209 std::shared_ptr<TickService> tick_service_;
210 };
211
212} // namespace quicr
const size_t total_buckets_
The total amount of buckets. Value is calculated by duration / interval.
Definition cache.h:194
void Clear() noexcept
Definition cache.h:131
void Insert(const K &key, T &&value, size_t ttl)
Definition cache.h:60
Cache()=delete
std::shared_ptr< TickService > tick_service_
Tick service for calculating new tick and jumps in time.
Definition cache.h:209
TickType current_ticks_
Last calculated tick value.
Definition cache.h:200
const size_t duration_
The duration in ticks of the entire queue.
Definition cache.h:188
ValueType Get(const K &key) noexcept
Definition cache.h:85
Cache(size_t duration, size_t interval, std::shared_ptr< TickService > tick_service)
Definition cache.h:31
CacheType cache_
The cache of elements being stored.
Definition cache.h:206
void Insert(const K &key, const T &value, size_t ttl)
Definition cache.h:58
bool Contains(const K &start_key, const K &end_key)
Definition cache.h:68
IndexType bucket_index_
The index in time of the current bucket.
Definition cache.h:197
bool Contains(const K &key) noexcept
Definition cache.h:62
ValueType First() noexcept
Definition cache.h:109
size_t Size() const noexcept
Definition cache.h:55
Cache(Cache &&) noexcept=default
Cache(const Cache &)=default
std::vector< ValueType > Get(const K &start_key, const K &end_key)
Definition cache.h:94
ValueType Last() noexcept
Definition cache.h:120
bool Empty() const noexcept
Definition cache.h:56
void InternalInsert(const K &key, Value value, size_t ttl)
Definition cache.h:169
void Advance()
Definition cache.h:142
const size_t interval_
The interval at which buckets are cleared in ticks.
Definition cache.h:191
std::vector< BucketType > buckets_
The memory storage for all keys to be managed.
Definition cache.h:203
Definition transport.h:28