136 const QList<QSharedPointer<T> > &values,
const QList<
int> &costs);
141 int maxCost_, minRecent_, maxOldPopular_;
142 int hitCount_, missCount_, promote_;
145 void unlink(Node *n);
146 void link_front(Node *n, Queue *q);
149template <
class Key,
class T,
class EvPolicy>
152 qDebug(
"\n=== cache %p ===",
this);
153 qDebug(
"hits: %d (%.2f%%)\tmisses: %d\tfill: %.2f%%", hitCount_,
154 100.0 *
float(hitCount_) / (
float(hitCount_ + missCount_)),
157 qDebug(
"q1g: size=%d, pop=%llu", q1_evicted_->size, q1_evicted_->pop);
158 qDebug(
"q1: cost=%d, size=%d, pop=%llu", q1_->cost, q1_->size, q1_->pop);
159 qDebug(
"q2: cost=%d, size=%d, pop=%llu", q2_->cost, q2_->size, q2_->pop);
160 qDebug(
"q3: cost=%d, size=%d, pop=%llu", q3_->cost, q3_->size, q3_->pop);
163template <
class Key,
class T,
class EvPolicy>
165 : q1_(
new Queue), q2_(
new Queue), q3_(
new Queue), q1_evicted_(
new Queue),
166 maxCost_(maxCost), minRecent_(minRecent), maxOldPopular_(maxOldPopular),
167 hitCount_(0), missCount_(0), promote_(0)
170 minRecent_ = maxCost_ / 3;
171 if (maxOldPopular_ < 0)
172 maxOldPopular_ = maxCost_ / 5;
175template <
class Key,
class T,
class EvPolicy>
178 Q_ASSERT(queueNumber >= 1 && queueNumber <= 4);
179 Queue *queue = queueNumber == 1 ? q1_ :
180 queueNumber == 2 ? q2_ :
181 queueNumber == 3 ? q3_ :
183 for (Node *node = queue->f; node; node = node->n)
184 buffer.append(node->v);
187template <
class Key,
class T,
class EvPolicy>
189 const QList<QSharedPointer<T> > &values,
const QList<
int> &costs)
191 Q_ASSERT(queueNumber >= 1 && queueNumber <= 4);
192 int bufferSize = keys.size();
196 Queue *queue = queueNumber == 1 ? q1_ :
197 queueNumber == 2 ? q2_ :
198 queueNumber == 3 ? q3_ :
200 for (
int i = 0; i<bufferSize; ++i) {
201 Node *node =
new Node;
204 node->cost = costs[i];
205 link_front(node, queue);
206 lookup_[keys[i]] = node;
211template <
class Key,
class T,
class EvPolicy>
215 minRecent_ = minRecent;
216 maxOldPopular_ = maxOldPopular;
218 minRecent_ = maxCost_ / 3;
219 if (maxOldPopular_ < 0)
220 maxOldPopular_ = maxCost_ / 5;
224template <
class Key,
class T,
class EvPolicy>
225bool QCache3Q<Key,T,EvPolicy>::
insert(
const Key &key, QSharedPointer<T> object,
int cost)
227 if (cost > maxCost_) {
231 [[maybe_unused]]
const auto oldSize = lookup_.size();
232 Node* &n = lookup_[key];
233 Q_ASSERT(
bool(n) == (lookup_.size() == oldSize));
237 n->q->cost -= n->cost;
241 if (n->q == q1_evicted_) {
242 if (n->pop > (uint)promote_) {
247 }
else if (n->q != q1_) {
268template <
class Key,
class T,
class EvPolicy>
271 while (q1_evicted_->f) {
272 Node *n = q1_evicted_->f;
280 EvPolicy::aboutToBeRemoved(n->k, n->v);
287 EvPolicy::aboutToBeRemoved(n->k, n->v);
294 EvPolicy::aboutToBeRemoved(n->k, n->v);
301template <
class Key,
class T,
class EvPolicy>
302void QCache3Q<Key,T,EvPolicy>::unlink(Node *n)
315 n->q->cost -= n->cost;
320template <
class Key,
class T,
class EvPolicy>
321void QCache3Q<Key,T,EvPolicy>::link_front(Node *n, Queue *q)
337template <
class Key,
class T,
class EvPolicy>
338void QCache3Q<Key,T,EvPolicy>::rebalance()
340 while (q1_evicted_->size > (q1_->size + q2_->size + q3_->size) * 4) {
341 Node *n = q1_evicted_->l;
343 lookup_.remove(n->k);
347 while ((q1_->cost + q2_->cost + q3_->cost) > maxCost_) {
348 if (q3_->cost > maxOldPopular_) {
351 EvPolicy::aboutToBeEvicted(n->k, n->v);
352 lookup_.remove(n->k);
354 }
else if (q1_->cost > minRecent_) {
357 EvPolicy::aboutToBeEvicted(n->k, n->v);
360 link_front(n, q1_evicted_);
364 if (q2_->size && n->pop > (q2_->pop / q2_->size)) {
367 EvPolicy::aboutToBeEvicted(n->k, n->v);
370 link_front(n, q1_evicted_);
376template <
class Key,
class T,
class EvPolicy>
379 const auto it = std::as_const(lookup_).find(key);
380 if (it == lookup_.cend())
385 if (n->q != q1_evicted_ && !force)
386 EvPolicy::aboutToBeRemoved(n->k, n->v);
391template <
class Key,
class T,
class EvPolicy>
394 return lookup_.keys();
397template <
class Key,
class T,
class EvPolicy>
400 if (!lookup_.contains(key)) {
401 const_cast<
QCache3Q<Key,T,EvPolicy> *>(
this)->missCount_++;
402 return QSharedPointer<T>();
405 QCache3Q<Key,T,EvPolicy> *me =
const_cast<
QCache3Q<Key,T,EvPolicy> *>(
this);
407 Node *n = me->lookup_[key];
414 if (n->pop > (quint64)promote_) {
416 me->link_front(n, q2_);
419 }
else if (n->q != q1_evicted_) {
424 me->link_front(n, q);
433template <
class Key,
class T,
class EvPolicy>