summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qapplicationstatic.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qapplicationstatic.h')
-rw-r--r--src/corelib/kernel/qapplicationstatic.h29
1 files changed, 17 insertions, 12 deletions
diff --git a/src/corelib/kernel/qapplicationstatic.h b/src/corelib/kernel/qapplicationstatic.h
index d2e050a911..bf5e79b8bf 100644
--- a/src/corelib/kernel/qapplicationstatic.h
+++ b/src/corelib/kernel/qapplicationstatic.h
@@ -9,6 +9,8 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qglobalstatic.h>
+#include <new>
+
QT_BEGIN_NAMESPACE
namespace QtGlobalStatic {
@@ -17,7 +19,7 @@ template <typename QAS> struct ApplicationHolder
using Type = typename QAS::QAS_Type;
using PlainType = std::remove_cv_t<Type>;
- Q_CONSTINIT static inline std::aligned_union_t<1, PlainType> storage = {};
+ Q_CONSTINIT static inline struct { alignas(Type) unsigned char data[sizeof(Type)]; } storage = {};
Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
Q_CONSTINIT static inline QBasicMutex mutex {};
@@ -28,7 +30,8 @@ template <typename QAS> struct ApplicationHolder
Q_DISABLE_COPY_MOVE(ApplicationHolder)
~ApplicationHolder()
{
- if (guard.loadRelaxed() == QtGlobalStatic::Initialized) {
+ if (guard.loadAcquire() == QtGlobalStatic::Initialized) {
+ // No mutex! Up to external code to ensure no race happens.
guard.storeRelease(QtGlobalStatic::Destroyed);
realPointer()->~PlainType();
}
@@ -36,30 +39,32 @@ template <typename QAS> struct ApplicationHolder
static PlainType *realPointer()
{
- return reinterpret_cast<PlainType *>(&storage);
+ return std::launder(reinterpret_cast<PlainType *>(&storage));
}
// called from QGlobalStatic::instance()
PlainType *pointer() noexcept(MutexLockIsNoexcept && ConstructionIsNoexcept)
{
- if (guard.loadRelaxed() == QtGlobalStatic::Initialized)
+ if (guard.loadAcquire() == QtGlobalStatic::Initialized)
return realPointer();
QMutexLocker locker(&mutex);
if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) {
- QAS::innerFunction(realPointer());
- QObject::connect(QCoreApplication::instance(), &QObject::destroyed, reset);
- guard.storeRelaxed(QtGlobalStatic::Initialized);
+ QAS::innerFunction(&storage);
+ const auto *app = QCoreApplication::instance();
+ Q_ASSERT_X(app, Q_FUNC_INFO,
+ "The application static was used without a QCoreApplication instance");
+ QObject::connect(app, &QObject::destroyed, app, reset, Qt::DirectConnection);
+ guard.storeRelease(QtGlobalStatic::Initialized);
}
return realPointer();
}
static void reset()
{
- if (guard.loadRelaxed() == QtGlobalStatic::Initialized) {
- QMutexLocker locker(&mutex);
- realPointer()->~PlainType();
- guard.storeRelaxed(QtGlobalStatic::Uninitialized);
- }
+ // we only synchronize using the mutex here, not the guard
+ QMutexLocker locker(&mutex);
+ realPointer()->~PlainType();
+ guard.storeRelaxed(QtGlobalStatic::Uninitialized);
}
};
} // namespace QtGlobalStatic