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