12using namespace std::chrono_literals;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
65 const qint64 costKb =
static_cast<qint64>(pixmap.width())
66 * pixmap.height() * pixmap.depth() / (8 * 1024);
67 const qint64 costMax = std::numeric_limits<qsizetype>::max();
69 return static_cast<qsizetype>(qBound(1LL, costKb, costMax));
74 if (Q_LIKELY(QThread::isMainThread()))
81
82
83
84
85
86
87
88
89
92
93
94QPixmapCache::Key::Key() : d(
nullptr)
99
100
101
102QPixmapCache::Key::Key(
const Key &other)
110
111
112QPixmapCache::Key::~Key()
114 if (d && --(d->ref) == 0)
119
120
121
122
123
124bool QPixmapCache::Key::operator ==(
const Key &key)
const
130
131
132
135
136
137
138
141
142
143
144
147
148
149
150
153
154
155
156
157bool QPixmapCache::Key::isValid()
const noexcept
159 return d && d->isValid;
163
164
165QPixmapCache::Key &QPixmapCache::Key::operator =(
const Key &other)
170 if (d && --(d->ref) == 0)
185 bool insert(
const QString& key,
const QPixmap &pixmap,
int cost);
188 bool remove(
const QPixmapCache::Key &key);
206 static constexpr auto soon_time = 10s;
207 static constexpr auto flush_time = 30s;
213 QHash<QString, QPixmapCache::Key> cacheKeys;
217QT_BEGIN_INCLUDE_NAMESPACE
218#include "qpixmapcache.moc"
219QT_END_INCLUDE_NAMESPACE
222
223
224
225
226size_t QPixmapCache::Key::hash(size_t seed)
const noexcept
228 return qHash(
this->d ?
this->d->key : 0, seed);
233 QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit_default),
234 keyArray(
nullptr), ps(0), keyArraySize(0), freeKey(0), t(
false)
244
245
246
247
248
249
250
251
252
253
254
255
256
260 const qsizetype currentTotal = totalCost();
261 const qsizetype oldSize = size();
263 setMaxCost(nt ? currentTotal * 3 / 4 : currentTotal - 1);
266 return size() != oldSize;
271 bool nt = totalCost() == ps;
274 }
else if (nt != t) {
275 timer.start(nt ? soon_time : flush_time,
this);
283 if (
const auto it = cacheKeys.find(key); it != cacheKeys.cend())
284 return object(it.value());
290 Q_ASSERT(key.isValid());
291 QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(key);
294 const_cast<
QPMCache *>(
this)->releaseKey(key);
304 auto k = insert(pixmap, cost);
306 k.d->stringKey = key;
307 cacheKeys[key] = std::move(k);
315 QPixmapCache::Key cacheKey = createKey();
316 bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey,
new QPixmapCacheEntry(cacheKey, pixmap), cost);
317 Q_ASSERT(success || !cacheKey.isValid());
319 if (!timer.isActive()) {
320 timer.start(flush_time,
this);
329 const auto cacheKey = cacheKeys.take(key);
330 return cacheKey.isValid() && remove(cacheKey);
335 return QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(key);
340 if (size <= keyArraySize || size == 0)
342 keyArray = q_check_ptr(
static_cast<
int *>(realloc(keyArray,
343 size *
sizeof(
int))));
344 for (
int i = keyArraySize; i != size; ++i)
351 if (freeKey == keyArraySize)
354 freeKey = keyArray[id];
355 QPixmapCache::Key key;
356 QPixmapCache::KeyData *d = QPMCache::getKeyData(&key);
363 QPixmapCache::KeyData *keyData = key.d;
366 if (!keyData->stringKey.isNull())
367 cacheKeys.remove(keyData->stringKey);
368 if (keyData->key > keyArraySize || keyData->key <= 0)
371 keyArray[keyData->key] = freeKey;
372 freeKey = keyData->key;
373 keyData->isValid =
false;
384 const QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QPixmapCacheEntry>::keys();
385 for (
const auto &key : keys) {
387 key.d->isValid =
false;
389 QCache<QPixmapCache::Key, QPixmapCacheEntry>::clear();
394QPixmapCache::KeyData*
QPMCache::getKeyData(QPixmapCache::Key *key)
397 key->d =
new QPixmapCache::KeyData;
403int Q_AUTOTEST_EXPORT q_QPixmapCache_keyHashSize()
405 return pm_cache()->size();
410 pm_cache()->releaseKey(key);
414
415
416
417
418
419
420
426 QPixmap *ptr = pm_cache()->object(key);
429 return ptr !=
nullptr;
433
434
435
436
437
438
444 if (!key.d || !key.d->isValid)
446 QPixmap *ptr = pm_cache()->object(key);
449 return ptr !=
nullptr;
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
476 return pm_cache()->insert(key, pixmap, cost(pixmap));
480
481
482
483
484
485
486
487
488
489
490
491
494 if (!qt_pixmapcache_thread_test())
495 return QPixmapCache::Key();
496 return pm_cache()->insert(pixmap, cost(pixmap));
499#if QT_DEPRECATED_SINCE(6
, 6
)
501
502
503
504
505
506
507
508
509
510
511
512
513
514
518
519
520
521
522
523
529 return pm_cache()->maxCost();
533
534
535
536
537
538
544 pm_cache()->setMaxCost(n);
548
549
554 pm_cache()->remove(key);
558
559
560
566 if (!key.d || !key.d->isValid)
568 pm_cache()->remove(key);
572
573
577 if (!QCoreApplication::closingDown() && !qt_pixmapcache_thread_test())
580 if (pm_cache.exists())
582 } QT_CATCH(
const std::bad_alloc &) {
592 pm_cache()->flushDetachedPixmaps(
true);
599 return (pm_cache()->totalCost()+1023) / 1024;
603
604
605
606
608
609
610
612
613
614
615
bool remove(const QString &key)
bool insert(const QString &key, const QPixmap &pixmap, int cost)
void releaseKey(const QPixmapCache::Key &key)
static QPixmapCache::KeyData * getKeyData(QPixmapCache::Key *key)
bool flushDetachedPixmaps(bool nt)
QPixmap * object(const QString &key) const
static QPixmapCache::KeyData * get(const QPixmapCache::Key &key)
void resizeKeyArray(int size)
QPixmapCache::Key createKey()
QPixmapCache::Key insert(const QPixmap &pixmap, int cost)
void timerEvent(QTimerEvent *) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
static const int cache_limit_default
static bool qt_pixmapcache_thread_test()
static qsizetype cost(const QPixmap &pixmap)
Q_AUTOTEST_EXPORT int qt_qpixmapcache_qpixmapcache_total_used()
Q_AUTOTEST_EXPORT void qt_qpixmapcache_flush_detached_pixmaps()