File indexing completed on 2025-09-17 09:09:07
0001
0002
0003
0004
0005 #ifndef QAPPLICATIONSTATIC_H
0006 #define QAPPLICATIONSTATIC_H
0007
0008 #include <QtCore/QMutex>
0009 #include <QtCore/qcoreapplication.h>
0010 #include <QtCore/qglobalstatic.h>
0011
0012 #include <new>
0013
0014 #if 0
0015 #pragma qt_class(QApplicationStatic)
0016 #endif
0017
0018 QT_BEGIN_NAMESPACE
0019
0020 namespace QtGlobalStatic {
0021 template <typename QAS> struct ApplicationHolder
0022 {
0023 using Type = typename QAS::QAS_Type;
0024 using PlainType = std::remove_cv_t<Type>;
0025
0026 Q_CONSTINIT static inline struct { alignas(Type) unsigned char data[sizeof(Type)]; } storage = {};
0027 Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
0028 Q_CONSTINIT static inline QBasicMutex mutex {};
0029
0030 static constexpr bool MutexLockIsNoexcept = noexcept(mutex.lock());
0031 static constexpr bool ConstructionIsNoexcept = noexcept(QAS::innerFunction(nullptr));
0032
0033 ApplicationHolder() = default;
0034 Q_DISABLE_COPY_MOVE(ApplicationHolder)
0035 ~ApplicationHolder()
0036 {
0037 if (guard.loadAcquire() == QtGlobalStatic::Initialized) {
0038
0039 guard.storeRelease(QtGlobalStatic::Destroyed);
0040 realPointer()->~PlainType();
0041 }
0042 }
0043
0044 static PlainType *realPointer()
0045 {
0046 return std::launder(reinterpret_cast<PlainType *>(&storage));
0047 }
0048
0049
0050 PlainType *pointer() noexcept(MutexLockIsNoexcept && ConstructionIsNoexcept)
0051 {
0052 if (guard.loadAcquire() == QtGlobalStatic::Initialized)
0053 return realPointer();
0054 QMutexLocker locker(&mutex);
0055 if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) {
0056 QAS::innerFunction(&storage);
0057 const auto *app = QCoreApplication::instance();
0058 Q_ASSERT_X(app, Q_FUNC_INFO,
0059 "The application static was used without a QCoreApplication instance");
0060 QObject::connect(app, &QObject::destroyed, app, reset, Qt::DirectConnection);
0061 guard.storeRelease(QtGlobalStatic::Initialized);
0062 }
0063 return realPointer();
0064 }
0065
0066 static void reset()
0067 {
0068
0069 QMutexLocker locker(&mutex);
0070 realPointer()->~PlainType();
0071 guard.storeRelaxed(QtGlobalStatic::Uninitialized);
0072 }
0073 };
0074 }
0075
0076 #define Q_APPLICATION_STATIC(TYPE, NAME, ...) \
0077 namespace { struct Q_QAS_ ## NAME { \
0078 typedef TYPE QAS_Type; \
0079 static void innerFunction(void *pointer) \
0080 noexcept(noexcept(std::remove_cv_t<QAS_Type>(__VA_ARGS__))) \
0081 { \
0082 new (pointer) QAS_Type(__VA_ARGS__); \
0083 } \
0084 }; } \
0085 static QGlobalStatic<QtGlobalStatic::ApplicationHolder<Q_QAS_ ## NAME>> NAME;\
0086
0087
0088 QT_END_NAMESPACE
0089
0090 #endif