QPixmapCache: guard against usage from non-main threads
Depending on the active QPA plugin, QPixmaps may now be created and used also in non-main threads. But QPixmapCache is not designed to be used from such threads, so add guards to ignore such access attempts, both from application code and from Qt library code. Such unsafe access would often cause a cryptical "~QObject: Timers cannot be stopped from another thread" warning; that also disappears with this fix. [ChangeLog][QtGui][QPixmapCache] Ignore unsafe access from non-main threads Task-number: QTBUG-76694 Task-number: QTBUG-72523 Change-Id: Ia2db37e528aec08bfb48808630bdf5e543689039 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
89aa6e780a
commit
2d597c0e1a
@ -42,6 +42,8 @@
|
||||
#include "qobject.h"
|
||||
#include "qdebug.h"
|
||||
#include "qpixmapcache_p.h"
|
||||
#include "qthread.h"
|
||||
#include "qcoreapplication.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -83,6 +85,9 @@ QT_BEGIN_NAMESPACE
|
||||
with QPixmapCache} explains how to use QPixmapCache to speed up
|
||||
applications by caching the results of painting.
|
||||
|
||||
\note QPixmapCache is only usable from the application's main thread.
|
||||
Access from other threads will be ignored and return failure.
|
||||
|
||||
\sa QCache, QPixmap
|
||||
*/
|
||||
|
||||
@ -98,6 +103,14 @@ static inline int cost(const QPixmap &pixmap)
|
||||
return static_cast<int>(qBound(1LL, costKb, costMax));
|
||||
}
|
||||
|
||||
static inline bool qt_pixmapcache_thread_test()
|
||||
{
|
||||
if (Q_LIKELY(QCoreApplication::instance() && QThread::currentThread() == QCoreApplication::instance()->thread()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QPixmapCache::Key
|
||||
\brief The QPixmapCache::Key class can be used for efficient access
|
||||
@ -487,6 +500,8 @@ QPixmapCacheEntry::~QPixmapCacheEntry()
|
||||
|
||||
QPixmap *QPixmapCache::find(const QString &key)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return nullptr;
|
||||
return pm_cache()->object(key);
|
||||
}
|
||||
|
||||
@ -515,6 +530,8 @@ bool QPixmapCache::find(const QString &key, QPixmap& pixmap)
|
||||
|
||||
bool QPixmapCache::find(const QString &key, QPixmap* pixmap)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return false;
|
||||
QPixmap *ptr = pm_cache()->object(key);
|
||||
if (ptr && pixmap)
|
||||
*pixmap = *ptr;
|
||||
@ -532,6 +549,8 @@ bool QPixmapCache::find(const QString &key, QPixmap* pixmap)
|
||||
*/
|
||||
bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return false;
|
||||
//The key is not valid anymore, a flush happened before probably
|
||||
if (!key.d || !key.d->isValid)
|
||||
return false;
|
||||
@ -563,6 +582,8 @@ bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
|
||||
|
||||
bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return false;
|
||||
return pm_cache()->insert(key, pixmap, cost(pixmap));
|
||||
}
|
||||
|
||||
@ -583,6 +604,8 @@ bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
|
||||
*/
|
||||
QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return QPixmapCache::Key();
|
||||
return pm_cache()->insert(pixmap, cost(pixmap));
|
||||
}
|
||||
|
||||
@ -597,6 +620,8 @@ QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
|
||||
*/
|
||||
bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return false;
|
||||
//The key is not valid anymore, a flush happened before probably
|
||||
if (!key.d || !key.d->isValid)
|
||||
return false;
|
||||
@ -626,6 +651,8 @@ int QPixmapCache::cacheLimit()
|
||||
|
||||
void QPixmapCache::setCacheLimit(int n)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return;
|
||||
pm_cache()->setMaxCost(n);
|
||||
}
|
||||
|
||||
@ -634,6 +661,8 @@ void QPixmapCache::setCacheLimit(int n)
|
||||
*/
|
||||
void QPixmapCache::remove(const QString &key)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return;
|
||||
pm_cache()->remove(key);
|
||||
}
|
||||
|
||||
@ -645,6 +674,8 @@ void QPixmapCache::remove(const QString &key)
|
||||
*/
|
||||
void QPixmapCache::remove(const Key &key)
|
||||
{
|
||||
if (!qt_pixmapcache_thread_test())
|
||||
return;
|
||||
//The key is not valid anymore, a flush happened before probably
|
||||
if (!key.d || !key.d->isValid)
|
||||
return;
|
||||
@ -657,6 +688,8 @@ void QPixmapCache::remove(const Key &key)
|
||||
|
||||
void QPixmapCache::clear()
|
||||
{
|
||||
if (!QCoreApplication::closingDown() && !qt_pixmapcache_thread_test())
|
||||
return;
|
||||
QT_TRY {
|
||||
if (pm_cache.exists())
|
||||
pm_cache->clear();
|
||||
|
Loading…
x
Reference in New Issue
Block a user