[Development] Removing the global static QObject from QPixmapCache
Sze Howe Koh
szehowe.koh at gmail.com
Sun May 30 07:28:40 CEST 2021
== Issue ==
There is a rule that "QCoreApplication should be the first QObject
created and last destroyed" [1]. However, there exists a violation to
this rule in Qt's internals -- QPixmapCache uses an internal global
static QObject (a QPMCache, to be precise) [2].
If initialized, the QPMCache outlives the QGuiApplication and gets
destroyed when the program/library is unloaded. This violates the rule
above.
This also causes problems when the QGuiApplication is created in a
std::thread instead of in main() (e.g. when a non-Qt application loads
a Qt-based plugin to display a GUI) -- The QPMCache destructor is run
by the wrong thread, which produces a warning, " QObject::~QObject:
Timers cannot be stopped from another thread ". There are also reports
that this can cause crashes [3][4].
== Proposal ==
QPMCache does not need the thread-safe initialization offered by
QGlobalStatic, since it can only be used from the Qt GUI thread. It
should also not outlive QGuiApplication.
So, I propose replacing QGlobalStatic<QPMCache> with
QPointer<QPMCache> as a simple self-cleaning singleton, and replacing
access to the global variable with QPMCache::instance():
QPointer<QPMCache> pm_cache;
QPMCache *QPMCache::instance() {
if (!pm_cache && qGuiApp && !qGuiApp->closingDown()) {
Q_ASSERT_X(QThread::currentThread() == qGuiApp->thread(),
"QPixmapCache initialization", "QPixmap can only be accessed from the
GUI thread");
pm_cache = new QPMCache;
connect(qGuiApp, &QGuiApplication::aboutToQuit, [] {
QPixmapCache::clear();
pm_cache->deleteLater();
});
}
return pm_cache;
}
I believe this approach should also take care of the ancient QTBUG-21807 [5]
Thoughts?
Regards,
Sze-Howe
[1] https://bugreports.qt.io/browse/QTBUG-71545?focusedCommentId=430042#comment-430042
[2] https://code.woboq.org/qt5/qtbase/src/gui/image/qpixmapcache.cpp.html#pm_cache
[3] https://forum.qt.io/topic/126128/qapplication-in-std-thread
[4] https://forum.qt.io/topic/126168/global-static-qpixmapcache-in-qt-internals
[5] https://bugreports.qt.io/browse/QTBUG-21807
More information about the Development
mailing list