135 const QList<QSharedPointer<T> > &values,
const QList<
int> &costs);
140 int maxCost_, minRecent_, maxOldPopular_;
141 int hitCount_, missCount_, promote_;
144 void unlink(Node *n);
145 void link_front(Node *n, Queue *q);
148template <
class Key,
class T,
class EvPolicy>
151 qDebug(
"\n=== cache %p ===",
this);
152 qDebug(
"hits: %d (%.2f%%)\tmisses: %d\tfill: %.2f%%", hitCount_,
153 100.0 *
float(hitCount_) / (
float(hitCount_ + missCount_)),
156 qDebug(
"q1g: size=%d, pop=%llu", q1_evicted_->size, q1_evicted_->pop);
157 qDebug(
"q1: cost=%d, size=%d, pop=%llu", q1_->cost, q1_->size, q1_->pop);
158 qDebug(
"q2: cost=%d, size=%d, pop=%llu", q2_->cost, q2_->size, q2_->pop);
159 qDebug(
"q3: cost=%d, size=%d, pop=%llu", q3_->cost, q3_->size, q3_->pop);
162template <
class Key,
class T,
class EvPolicy>
164 : q1_(
new Queue), q2_(
new Queue), q3_(
new Queue), q1_evicted_(
new Queue),
165 maxCost_(maxCost), minRecent_(minRecent), maxOldPopular_(maxOldPopular),
166 hitCount_(0), missCount_(0), promote_(0)
169 minRecent_ = maxCost_ / 3;
170 if (maxOldPopular_ < 0)
171 maxOldPopular_ = maxCost_ / 5;
174template <
class Key,
class T,
class EvPolicy>
177 Q_ASSERT(queueNumber >= 1 && queueNumber <= 4);
178 Queue *queue = queueNumber == 1 ? q1_ :
179 queueNumber == 2 ? q2_ :
180 queueNumber == 3 ? q3_ :
182 for (Node *node = queue->f; node; node = node->n)
183 buffer.append(node->v);
186template <
class Key,
class T,
class EvPolicy>
188 const QList<QSharedPointer<T> > &values,
const QList<
int> &costs)
190 Q_ASSERT(queueNumber >= 1 && queueNumber <= 4);
191 int bufferSize = keys.size();
195 Queue *queue = queueNumber == 1 ? q1_ :
196 queueNumber == 2 ? q2_ :
197 queueNumber == 3 ? q3_ :
199 for (
int i = 0; i<bufferSize; ++i) {
200 Node *node =
new Node;
203 node->cost = costs[i];
204 link_front(node, queue);
205 lookup_[keys[i]] = node;
210template <
class Key,
class T,
class EvPolicy>
214 minRecent_ = minRecent;
215 maxOldPopular_ = maxOldPopular;
217 minRecent_ = maxCost_ / 3;
218 if (maxOldPopular_ < 0)
219 maxOldPopular_ = maxCost_ / 5;
223template <
class Key,
class T,
class EvPolicy>
224bool QCache3Q<Key,T,EvPolicy>::
insert(
const Key &key, QSharedPointer<T> object,
int cost)
226 if (cost > maxCost_) {
230 [[maybe_unused]]
const auto oldSize = lookup_.size();
231 Node* &n = lookup_[key];
232 Q_ASSERT(
bool(n) == (lookup_.size() == oldSize));
236 n->q->cost -= n->cost;
240 if (n->q == q1_evicted_) {
241 if (n->pop > (uint)promote_) {
246 }
else if (n->q != q1_) {
267template <
class Key,
class T,
class EvPolicy>
270 while (q1_evicted_->f) {
271 Node *n = q1_evicted_->f;
279 EvPolicy::aboutToBeRemoved(n->k, n->v);
286 EvPolicy::aboutToBeRemoved(n->k, n->v);
293 EvPolicy::aboutToBeRemoved(n->k, n->v);
300template <
class Key,
class T,
class EvPolicy>
301void QCache3Q<Key,T,EvPolicy>::unlink(Node *n)
314 n->q->cost -= n->cost;
319template <
class Key,
class T,
class EvPolicy>
320void QCache3Q<Key,T,EvPolicy>::link_front(Node *n, Queue *q)
336template <
class Key,
class T,
class EvPolicy>
337void QCache3Q<Key,T,EvPolicy>::rebalance()
339 while (q1_evicted_->size > (q1_->size + q2_->size + q3_->size) * 4) {
340 Node *n = q1_evicted_->l;
342 lookup_.remove(n->k);
346 while ((q1_->cost + q2_->cost + q3_->cost) > maxCost_) {
347 if (q3_->cost > maxOldPopular_) {
350 EvPolicy::aboutToBeEvicted(n->k, n->v);
351 lookup_.remove(n->k);
353 }
else if (q1_->cost > minRecent_) {
356 EvPolicy::aboutToBeEvicted(n->k, n->v);
359 link_front(n, q1_evicted_);
363 if (q2_->size && n->pop > (q2_->pop / q2_->size)) {
366 EvPolicy::aboutToBeEvicted(n->k, n->v);
369 link_front(n, q1_evicted_);
375template <
class Key,
class T,
class EvPolicy>
378 const auto it = std::as_const(lookup_).find(key);
379 if (it == lookup_.cend())
384 if (n->q != q1_evicted_ && !force)
385 EvPolicy::aboutToBeRemoved(n->k, n->v);
390template <
class Key,
class T,
class EvPolicy>
393 return lookup_.keys();
396template <
class Key,
class T,
class EvPolicy>
399 if (!lookup_.contains(key)) {
400 const_cast<
QCache3Q<Key,T,EvPolicy> *>(
this)->missCount_++;
401 return QSharedPointer<T>();
404 QCache3Q<Key,T,EvPolicy> *me =
const_cast<
QCache3Q<Key,T,EvPolicy> *>(
this);
406 Node *n = me->lookup_[key];
413 if (n->pop > (quint64)promote_) {
415 me->link_front(n, q2_);
418 }
else if (n->q != q1_evicted_) {
423 me->link_front(n, q);
432template <
class Key,
class T,
class EvPolicy>