diff options
Diffstat (limited to 'src/corelib/kernel/qapplicationstatic.h')
-rw-r--r-- | src/corelib/kernel/qapplicationstatic.h | 29 |
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 |