Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qcache3q_p.h
Go to the documentation of this file.
1
// Copyright (C) 2021 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:critical reason:custom-container
4
5
#
ifndef
QCACHE3Q_H
6
#
define
QCACHE3Q_H
7
8
//
9
// W A R N I N G
10
// -------------
11
//
12
// This file is not part of the Qt API. It exists purely as an
13
// implementation detail. This header file may change from version to
14
// version without notice, or even be removed.
15
//
16
// We mean it.
17
18
#
include
<
QtCore
/
QSharedPointer
>
19
#
include
<
QtCore
/
QDebug
>
20
21
QT_BEGIN_NAMESPACE
22
23
template
<
class
Key,
class
T>
24
class
QCache3QDefaultEvictionPolicy
25
{
26
protected
:
27
/* called just before a key/value pair is about to be _evicted_ */
28
void
aboutToBeEvicted(
const
Key &key, QSharedPointer<T> obj);
29
/* called just before a key/value pair is about to be removed, by
30
* clear(), remove() or by the destructor (which calls clear) */
31
void
aboutToBeRemoved(
const
Key &key, QSharedPointer<T> obj);
32
};
33
34
template
<
class
Key,
class
T>
35
void
QCache3QDefaultEvictionPolicy<Key,T>::aboutToBeEvicted(
const
Key &key, QSharedPointer<T> obj)
36
{
37
Q_UNUSED(key);
38
Q_UNUSED(obj);
39
}
40
41
template
<
class
Key,
class
T>
42
void
QCache3QDefaultEvictionPolicy<Key,T>::aboutToBeRemoved(
const
Key &key, QSharedPointer<T> obj)
43
{
44
Q_UNUSED(key);
45
Q_UNUSED(obj);
46
}
47
48
/*
49
* QCache3Q
50
*
51
* A cache template class for managing QSharedPointers to objects with an
52
* associated key. It's a lot like QCache, but uses an alternative algorithm
53
* '3Q' -- which is the '2Q' algorithm plus an extra queue for previously popular
54
* but evicted nodes, and a 'ghost' list of recent evictions to make a better
55
* placement choice if they are requested again.
56
*
57
* New nodes enter the cache on the "newbies" queue, which is evicted LRA
58
* (least-recently-added). If a newbie is popular enough (it has been requested
59
* more than promoteAt times), it will be promoted to a "regular". Regulars
60
* are evicted LRU (least-recently-used). If a regular is under consideration
61
* for eviction, its popularity is compared to the mean popularity of the whole
62
* regulars queue. If it is greater, it is instead moved to the "hobos" queue.
63
* The "hobos" queue is also evicted LRU, but has a maximum size constraint
64
* so eviction from it is less likely than from the regulars.
65
*
66
* Tweakables:
67
* * maxCost = maximum total cost for the whole cache
68
* * minRecent = minimum size that q1 ("newbies") has to be before eviction
69
* from it takes place
70
* * maxOldPopular = maximum size that q3 ("hobos") can reach before eviction
71
* from it takes place
72
* * promoteAt = minimum popularity necessary to promote a node from
73
* "newbie" to "regular"
74
*/
75
template
<
class
Key,
class
T,
class
EvPolicy = QCache3QDefaultEvictionPolicy<Key,T> >
76
class
QCache3Q
:
public
EvPolicy
77
{
78
Q_DISABLE_COPY_MOVE
(
QCache3Q
)
79
private
:
80
class
Queue
;
81
class
Node
82
{
83
public
:
84
inline
explicit
Node() : q(0), n(0), p(0), pop(0), cost(0) {}
85
86
Queue *q;
87
Node *n;
88
Node *p;
89
Key k;
90
QSharedPointer<T> v;
91
quint64 pop;
// popularity, incremented each ping
92
int
cost;
93
};
94
95
class
Queue
96
{
97
public
:
98
inline
explicit
Queue() : f(0), l(0), cost(0), pop(0), size(0) {}
99
100
Node *f;
101
Node *l;
102
int
cost;
// total cost of nodes on the queue
103
quint64 pop;
// sum of popularity values on the queue
104
int
size;
// size of the queue
105
};
106
107
Queue *q1_;
// "newbies": seen only once, evicted LRA (least-recently-added)
108
Queue *q2_;
// regular nodes, promoted from newbies, evicted LRU
109
Queue *q3_;
// "hobos": evicted from q2 but were very popular (above mean)
110
Queue *q1_evicted_;
// ghosts of recently evicted newbies and regulars
111
QHash<Key, Node *> lookup_;
112
113
public
:
114
explicit
QCache3Q
(
int
maxCost = 0,
int
minRecent = -1,
int
maxOldPopular = -1);
115
inline
~
QCache3Q
() {
clear
(
)
;
delete
q1_;
delete
q2_;
delete
q3_;
delete
q1_evicted_; }
116
117
inline
int
maxCost
()
const
{
return
maxCost_; }
118
void
setMaxCost
(
int
maxCost,
int
minRecent = -1,
int
maxOldPopular = -1);
119
120
inline
int
promoteAt
()
const
{
return
promote_; }
121
inline
void
setPromoteAt
(
int
p) { promote_ = p; }
122
123
inline
int
totalCost
()
const
{
return
q1_->cost + q2_->cost + q3_->cost; }
124
125
void
clear
();
126
bool
insert
(
const
Key &key, QSharedPointer<T> object,
int
cost = 1);
127
QSharedPointer
<
T
>
object
(
const
Key &key)
const
;
128
QSharedPointer
<
T
>
operator
[](
const
Key &key)
const
;
129
130
void
remove
(
const
Key &key,
bool
force =
false
);
131
QList
<
Key
>
keys
()
const
;
132
void
printStats
();
133
134
// Copy data directly into a queue. Designed for single use after construction
135
void
deserializeQueue
(
int
queueNumber,
const
QList<Key> &keys,
136
const
QList<QSharedPointer<T> > &values,
const
QList<
int
> &costs);
137
// Copy data from specific queue into list
138
void
serializeQueue
(
int
queueNumber, QList<QSharedPointer<T> > &buffer);
139
140
private
:
141
int
maxCost_, minRecent_, maxOldPopular_;
142
int
hitCount_, missCount_, promote_;
143
144
void
rebalance();
145
void
unlink(Node *n);
146
void
link_front(Node *n, Queue *q);
147
};
148
149
template
<
class
Key,
class
T,
class
EvPolicy>
150
void
QCache3Q
<Key,T,EvPolicy>::
printStats
()
151
{
152
qDebug(
"\n=== cache %p ==="
,
this
);
153
qDebug(
"hits: %d (%.2f%%)\tmisses: %d\tfill: %.2f%%"
, hitCount_,
154
100.0 *
float
(hitCount_) / (
float
(hitCount_ + missCount_)),
155
missCount_,
156
100.0 *
float
(
totalCost
(
)
) /
float
(
maxCost
(
)
));
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);
161
}
162
163
template
<
class
Key,
class
T,
class
EvPolicy>
164
QCache3Q
<Key,T,EvPolicy>::
QCache3Q
(
int
maxCost,
int
minRecent,
int
maxOldPopular)
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)
168
{
169
if
(minRecent_ < 0)
170
minRecent_ = maxCost_ / 3;
171
if
(maxOldPopular_ < 0)
172
maxOldPopular_ = maxCost_ / 5;
173
}
174
175
template
<
class
Key,
class
T,
class
EvPolicy>
176
void
QCache3Q
<Key,T,EvPolicy>::
serializeQueue
(
int
queueNumber, QList<QSharedPointer<T> > &buffer)
177
{
178
Q_ASSERT(queueNumber >= 1 && queueNumber <= 4);
179
Queue *queue = queueNumber == 1 ? q1_ :
180
queueNumber == 2 ? q2_ :
181
queueNumber == 3 ? q3_ :
182
q1_evicted_;
183
for
(Node *node = queue->f; node; node = node->n)
184
buffer.append(node->v);
185
}
186
187
template
<
class
Key,
class
T,
class
EvPolicy>
188
void
QCache3Q
<Key,T,EvPolicy>::
deserializeQueue
(
int
queueNumber,
const
QList<Key> &keys,
189
const
QList<QSharedPointer<T> > &values,
const
QList<
int
> &costs)
190
{
191
Q_ASSERT(queueNumber >= 1 && queueNumber <= 4);
192
int
bufferSize = keys.size();
193
if
(bufferSize == 0)
194
return
;
195
clear
(
)
;
196
Queue *queue = queueNumber == 1 ? q1_ :
197
queueNumber == 2 ? q2_ :
198
queueNumber == 3 ? q3_ :
199
q1_evicted_;
200
for
(
int
i = 0; i<bufferSize; ++i) {
201
Node *node =
new
Node;
202
node->v = values[i];
203
node->k = keys[i];
204
node->cost = costs[i];
205
link_front(node, queue);
206
lookup_[keys[i]] = node;
207
}
208
}
209
210
211
template
<
class
Key,
class
T,
class
EvPolicy>
212
inline
void
QCache3Q
<Key,T,EvPolicy>::
setMaxCost
(
int
maxCost,
int
minRecent,
int
maxOldPopular)
213
{
214
maxCost_ = maxCost;
215
minRecent_ = minRecent;
216
maxOldPopular_ = maxOldPopular;
217
if
(minRecent_ < 0)
218
minRecent_ = maxCost_ / 3;
219
if
(maxOldPopular_ < 0)
220
maxOldPopular_ = maxCost_ / 5;
221
rebalance();
222
}
223
224
template
<
class
Key,
class
T,
class
EvPolicy>
225
bool
QCache3Q
<Key,T,EvPolicy>::
insert
(
const
Key &key, QSharedPointer<T> object,
int
cost)
226
{
227
if
(cost > maxCost_) {
228
return
false
;
229
}
230
231
[[maybe_unused]]
const
auto
oldSize = lookup_.size();
232
Node* &n = lookup_[key];
233
Q_ASSERT(
bool
(n) == (lookup_.size() == oldSize));
// either a new nullptr, or existing non-null
234
235
if
(n) {
236
n->v = object;
237
n->q->cost -= n->cost;
238
n->cost = cost;
239
n->q->cost += cost;
240
241
if
(n->q == q1_evicted_) {
242
if
(n->pop > (uint)promote_) {
243
unlink(n);
244
link_front(n, q2_);
245
rebalance();
246
}
247
}
else
if
(n->q != q1_) {
248
Queue *q = n->q;
249
unlink(n);
250
link_front(n, q);
251
rebalance();
252
}
253
254
return
true
;
255
}
256
257
n =
new
Node;
258
n->v = object;
259
n->k = key;
260
n->cost = cost;
261
link_front(n, q1_);
262
263
rebalance();
264
265
return
true
;
266
}
267
268
template
<
class
Key,
class
T,
class
EvPolicy>
269
void
QCache3Q
<Key,T,EvPolicy>::
clear
()
270
{
271
while
(q1_evicted_->f) {
272
Node *n = q1_evicted_->f;
273
unlink(n);
274
delete
n;
275
}
276
277
while
(q1_->f) {
278
Node *n = q1_->f;
279
unlink(n);
280
EvPolicy::aboutToBeRemoved(n->k, n->v);
281
delete
n;
282
}
283
284
while
(q2_->f) {
285
Node *n = q2_->f;
286
unlink(n);
287
EvPolicy::aboutToBeRemoved(n->k, n->v);
288
delete
n;
289
}
290
291
while
(q3_->f) {
292
Node *n = q3_->f;
293
unlink(n);
294
EvPolicy::aboutToBeRemoved(n->k, n->v);
295
delete
n;
296
}
297
298
lookup_.clear();
299
}
300
301
template
<
class
Key,
class
T,
class
EvPolicy>
302
void
QCache3Q
<Key,T,EvPolicy>::unlink(Node *n)
303
{
304
if
(n->n)
305
n->n->p = n->p;
306
if
(n->p)
307
n->p->n = n->n;
308
if
(n->q->f == n)
309
n->q->f = n->n;
310
if
(n->q->l == n)
311
n->q->l = n->p;
312
n->n = 0;
313
n->p = 0;
314
n->q->pop -= n->pop;
315
n->q->cost -= n->cost;
316
n->q->size--;
317
n->q = 0;
318
}
319
320
template
<
class
Key,
class
T,
class
EvPolicy>
321
void
QCache3Q
<Key,T,EvPolicy>::link_front(Node *n, Queue *q)
322
{
323
n->n = q->f;
324
n->p = 0;
325
n->q = q;
326
if
(q->f)
327
q->f->p = n;
328
q->f = n;
329
if
(!q->l)
330
q->l = n;
331
332
q->pop += n->pop;
333
q->cost += n->cost;
334
q->size++;
335
}
336
337
template
<
class
Key,
class
T,
class
EvPolicy>
338
void
QCache3Q
<Key,T,EvPolicy>::rebalance()
339
{
340
while
(q1_evicted_->size > (q1_->size + q2_->size + q3_->size) * 4) {
341
Node *n = q1_evicted_->l;
342
unlink(n);
343
lookup_.remove(n->k);
344
delete
n;
345
}
346
347
while
((q1_->cost + q2_->cost + q3_->cost) > maxCost_) {
348
if
(q3_->cost > maxOldPopular_) {
349
Node *n = q3_->l;
350
unlink(n);
351
EvPolicy::aboutToBeEvicted(n->k, n->v);
352
lookup_.remove(n->k);
353
delete
n;
354
}
else
if
(q1_->cost > minRecent_) {
355
Node *n = q1_->l;
356
unlink(n);
357
EvPolicy::aboutToBeEvicted(n->k, n->v);
358
n->v.clear();
359
n->cost = 0;
360
link_front(n, q1_evicted_);
361
}
else
{
362
Node *n = q2_->l;
363
unlink(n);
364
if
(q2_->size && n->pop > (q2_->pop / q2_->size)) {
365
link_front(n, q3_);
366
}
else
{
367
EvPolicy::aboutToBeEvicted(n->k, n->v);
368
n->v.clear();
369
n->cost = 0;
370
link_front(n, q1_evicted_);
371
}
372
}
373
}
374
}
375
376
template
<
class
Key,
class
T,
class
EvPolicy>
377
void
QCache3Q
<Key,T,EvPolicy>::
remove
(
const
Key &key,
bool
force)
378
{
379
const
auto
it = std::as_const(lookup_).find(key);
380
if
(it == lookup_.cend())
381
return
;
382
383
Node *n = *it;
384
unlink(n);
385
if
(n->q != q1_evicted_ && !force)
386
EvPolicy::aboutToBeRemoved(n->k, n->v);
387
lookup_.erase(it);
388
delete
n;
389
}
390
391
template
<
class
Key,
class
T,
class
EvPolicy>
392
QList
<
Key
>
QCache3Q
<Key,T,EvPolicy>::
keys
()
const
393
{
394
return
lookup_.keys();
395
}
396
397
template
<
class
Key,
class
T,
class
EvPolicy>
398
QSharedPointer
<
T
>
QCache3Q
<Key,T,EvPolicy>::
object
(
const
Key &key)
const
399
{
400
if
(!lookup_.contains(key)) {
401
const_cast
<
QCache3Q
<Key,T,EvPolicy> *>(
this
)->missCount_++;
402
return
QSharedPointer<T>();
403
}
404
405
QCache3Q
<Key,T,EvPolicy> *me =
const_cast
<
QCache3Q
<Key,T,EvPolicy> *>(
this
);
406
407
Node *n = me->lookup_[key];
408
n->pop++;
409
n->q->pop++;
410
411
if
(n->q == q1_) {
412
me->hitCount_++;
413
414
if
(n->pop > (quint64)promote_) {
415
me->unlink(n);
416
me->link_front(n, q2_);
417
me->rebalance();
418
}
419
}
else
if
(n->q != q1_evicted_) {
420
me->hitCount_++;
421
422
Queue *q = n->q;
423
me->unlink(n);
424
me->link_front(n, q);
425
me->rebalance();
426
}
else
{
427
me->missCount_++;
428
}
429
430
return
n->v;
431
}
432
433
template
<
class
Key,
class
T,
class
EvPolicy>
434
inline
QSharedPointer
<
T
>
QCache3Q
<Key,T,EvPolicy>::
operator
[](
const
Key &key)
const
435
{
436
return
object(key);
437
}
438
439
QT_END_NAMESPACE
440
441
#
endif
// QCACHE3Q_H
QCache3QTileEvictionPolicy
Definition
qgeofiletilecache_p.h:51
QCache3Q
Definition
qcache3q_p.h:77
QCache3Q::totalCost
int totalCost() const
Definition
qcache3q_p.h:123
QCache3Q::clear
void clear()
Definition
qcache3q_p.h:269
QCache3Q::operator[]
QSharedPointer< T > operator[](const Key &key) const
Definition
qcache3q_p.h:434
QCache3Q::maxCost
int maxCost() const
Definition
qcache3q_p.h:117
QCache3Q::QCache3Q
QCache3Q(int maxCost=0, int minRecent=-1, int maxOldPopular=-1)
Definition
qcache3q_p.h:164
QCache3Q::deserializeQueue
void deserializeQueue(int queueNumber, const QList< Key > &keys, const QList< QSharedPointer< T > > &values, const QList< int > &costs)
Definition
qcache3q_p.h:188
QCache3Q::insert
bool insert(const Key &key, QSharedPointer< T > object, int cost=1)
Definition
qcache3q_p.h:225
QCache3Q::remove
void remove(const Key &key, bool force=false)
Definition
qcache3q_p.h:377
QCache3Q::~QCache3Q
~QCache3Q()
Definition
qcache3q_p.h:115
QCache3Q::object
QSharedPointer< T > object(const Key &key) const
Definition
qcache3q_p.h:398
QCache3Q::setMaxCost
void setMaxCost(int maxCost, int minRecent=-1, int maxOldPopular=-1)
Definition
qcache3q_p.h:212
QCache3Q::printStats
void printStats()
Definition
qcache3q_p.h:150
QCache3Q::promoteAt
int promoteAt() const
Definition
qcache3q_p.h:120
QCache3Q::keys
QList< Key > keys() const
Definition
qcache3q_p.h:392
QCache3Q::setPromoteAt
void setPromoteAt(int p)
Definition
qcache3q_p.h:121
QCache3Q::serializeQueue
void serializeQueue(int queueNumber, QList< QSharedPointer< T > > &buffer)
Definition
qcache3q_p.h:176
QGeoCachedTileDisk
Definition
qgeofiletilecache_p.h:38
QGeoCachedTileDisk::cache
QGeoFileTileCache * cache
Definition
qgeofiletilecache_p.h:45
QGeoCachedTileDisk::filename
QString filename
Definition
qgeofiletilecache_p.h:43
QGeoCachedTileDisk::format
QString format
Definition
qgeofiletilecache_p.h:44
QGeoCachedTileDisk::spec
QGeoTileSpec spec
Definition
qgeofiletilecache_p.h:42
QGeoCachedTileDisk::~QGeoCachedTileDisk
~QGeoCachedTileDisk()
Definition
qgeofiletilecache.cpp:51
QGeoCachedTileMemory
Definition
qgeofiletilecache.cpp:23
QGeoCachedTileMemory::cache
QGeoFileTileCache * cache
Definition
qgeofiletilecache.cpp:32
QGeoCachedTileMemory::format
QString format
Definition
qgeofiletilecache.cpp:34
QGeoCachedTileMemory::~QGeoCachedTileMemory
~QGeoCachedTileMemory()
Definition
qgeofiletilecache.cpp:25
QGeoCachedTileMemory::bytes
QByteArray bytes
Definition
qgeofiletilecache.cpp:33
QGeoCachedTileMemory::spec
QGeoTileSpec spec
Definition
qgeofiletilecache.cpp:31
QGeoFileTileCache
Definition
qgeofiletilecache_p.h:58
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtlocation
src
location
maps
qcache3q_p.h
Generated on
for Qt by
1.18.0