13using namespace std::chrono_literals;
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
59
66 const qint64 costKb =
static_cast<qint64>(pixmap.width())
67 * pixmap.height() * pixmap.depth() / (8 * 1024);
68 const qint64 costMax = std::numeric_limits<qsizetype>::max();
70 return static_cast<qsizetype>(qBound(1LL, costKb, costMax));
75 if (Q_LIKELY(QThread::isMainThread()))
82
83
84
85
86
87
88
89
90
93
94
95QPixmapCache::Key::Key() : d(
nullptr)
100
101
102
103QPixmapCache::Key::Key(
const Key &other)
111
112
113QPixmapCache::Key::~Key()
115 if (d && --(d->ref) == 0)
120
121
122
123
124
125bool QPixmapCache::Key::operator ==(
const Key &key)
const
131
132
133
136
137
138
139
142
143
144
145
148
149
150
151
154
155
156
157
158bool QPixmapCache::Key::isValid()
const noexcept
160 return d && d->isValid;
164
165
166QPixmapCache::Key &QPixmapCache::Key::operator =(
const Key &other)
171 if (d && --(d->ref) == 0)
186 bool insert(
const QString& key,
const QPixmap &pixmap,
int cost);
189 bool remove(
const QPixmapCache::Key &key);
207 static constexpr auto soon_time = 10s;
208 static constexpr auto flush_time = 30s;
214 QHash<QString, QPixmapCache::Key> cacheKeys;
218QT_BEGIN_INCLUDE_NAMESPACE
219#include "qpixmapcache.moc"
220QT_END_INCLUDE_NAMESPACE
223
224
225
226
227size_t QPixmapCache::Key::hash(size_t seed)
const noexcept
229 return qHash(
this->d ?
this->d->key : 0, seed);
234 QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit_default),
235 keyArray(
nullptr), ps(0), keyArraySize(0), freeKey(0), t(
false)
245
246
247
248
249
250
251
252
253
254
255
256
257
261 const qsizetype currentTotal = totalCost();
262 const qsizetype oldSize = size();
264 setMaxCost(nt ? currentTotal * 3 / 4 : currentTotal - 1);
267 return size() != oldSize;
272 bool nt = totalCost() == ps;
275 }
else if (nt != t) {
276 timer.start(nt ? soon_time : flush_time,
this);
284 if (
const auto it = cacheKeys.find(key); it != cacheKeys.cend())
285 return object(it.value());
291 Q_ASSERT(key.isValid());
292 QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(key);
295 const_cast<
QPMCache *>(
this)->releaseKey(key);
305 auto k = insert(pixmap, cost);
307 k.d->stringKey = key;
308 cacheKeys[key] = std::move(k);
316 QPixmapCache::Key cacheKey = createKey();
317 bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey,
new QPixmapCacheEntry(cacheKey, pixmap), cost);
318 Q_ASSERT(success || !cacheKey.isValid());
320 if (!timer.isActive()) {
321 timer.start(flush_time,
this);
330 const auto cacheKey = cacheKeys.take(key);
331 return cacheKey.isValid() && remove(cacheKey);
336 return QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(key);
341 if (size <= keyArraySize || size == 0)
343 keyArray = q_check_ptr(
static_cast<
int *>(realloc(keyArray,
344 size *
sizeof(
int))));
345 for (
int i = keyArraySize; i != size; ++i)
352 if (freeKey == keyArraySize)
355 freeKey = keyArray[id];
356 QPixmapCache::Key key;
357 QPixmapCache::KeyData *d = QPMCache::getKeyData(&key);
364 QPixmapCache::KeyData *keyData = key.d;
367 if (!keyData->stringKey.isNull())
368 cacheKeys.remove(keyData->stringKey);
369 if (keyData->key > keyArraySize || keyData->key <= 0)
372 keyArray[keyData->key] = freeKey;
373 freeKey = keyData->key;
374 keyData->isValid =
false;
385 const QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QPixmapCacheEntry>::keys();
386 for (
const auto &key : keys) {
388 key.d->isValid =
false;
390 QCache<QPixmapCache::Key, QPixmapCacheEntry>::clear();
395QPixmapCache::KeyData*
QPMCache::getKeyData(QPixmapCache::Key *key)
398 key->d =
new QPixmapCache::KeyData;
404int Q_AUTOTEST_EXPORT q_QPixmapCache_keyHashSize()
406 return pm_cache()->size();
411 pm_cache()->releaseKey(key);
415
416
417
418
419
420
421
427 QPixmap *ptr = pm_cache()->object(key);
430 return ptr !=
nullptr;
434
435
436
437
438
439
445 if (!key.d || !key.d->isValid)
447 QPixmap *ptr = pm_cache()->object(key);
450 return ptr !=
nullptr;
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
477 return pm_cache()->insert(key, pixmap, cost(pixmap));
481
482
483
484
485
486
487
488
489
490
491
492
495 if (!qt_pixmapcache_thread_test())
496 return QPixmapCache::Key();
497 return pm_cache()->insert(pixmap, cost(pixmap));
500#if QT_DEPRECATED_SINCE(6
, 6
)
502
503
504
505
506
507
508
509
510
511
512
513
514
515
519
520
521
522
523
524
530 return pm_cache()->maxCost();
534
535
536
537
538
539
545 pm_cache()->setMaxCost(n);
549
550
555 pm_cache()->remove(key);
559
560
561
567 if (!key.d || !key.d->isValid)
569 pm_cache()->remove(key);
573
574
578 if (!QCoreApplication::closingDown() && !qt_pixmapcache_thread_test())
581 if (pm_cache.exists())
583 } QT_CATCH(
const std::bad_alloc &) {
593 pm_cache()->flushDetachedPixmaps(
true);
600 return (pm_cache()->totalCost()+1023) / 1024;
604
605
606
607
609
610
611
613
614
615
616
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()