File indexing completed on 2026-09-15 09:19:54
0001
0002
0003
0004
0005 #ifndef QGLOBALSTATIC_H
0006 #define QGLOBALSTATIC_H
0007
0008 #include <QtCore/qassert.h>
0009 #include <QtCore/qatomic.h>
0010 #include <QtCore/qtclasshelpermacros.h>
0011
0012 #include <atomic> // for bootstrapped (no thread) builds
0013 #include <type_traits>
0014
0015 QT_BEGIN_NAMESPACE
0016
0017 namespace QtGlobalStatic {
0018 enum GuardValues {
0019 Destroyed = -2,
0020 Initialized = -1,
0021 Uninitialized = 0,
0022 Initializing = 1
0023 };
0024
0025 template <typename QGS> union Holder
0026 {
0027 using Type = typename QGS::QGS_Type;
0028 using PlainType = std::remove_cv_t<Type>;
0029
0030 static constexpr bool ConstructionIsNoexcept = noexcept(QGS::innerFunction(nullptr));
0031 Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
0032
0033
0034 PlainType storage;
0035
0036 Holder() noexcept(ConstructionIsNoexcept)
0037 {
0038 QGS::innerFunction(pointer());
0039 guard.storeRelaxed(QtGlobalStatic::Initialized);
0040 }
0041
0042 ~Holder()
0043 {
0044
0045
0046
0047
0048 QT_WARNING_PUSH
0049 #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
0050 QT_WARNING_DISABLE_GCC("-Wtsan")
0051 #endif
0052
0053 std::atomic_thread_fence(std::memory_order_acquire);
0054 QT_WARNING_POP
0055 pointer()->~PlainType();
0056 guard.storeRelease(QtGlobalStatic::Destroyed);
0057 }
0058
0059 PlainType *pointer() noexcept
0060 {
0061 return &storage;
0062 }
0063
0064 Q_DISABLE_COPY_MOVE(Holder)
0065 };
0066 }
0067
0068 template <typename Holder> struct QGlobalStatic
0069 {
0070 using Type = typename Holder::Type;
0071
0072 bool isDestroyed() const noexcept { return guardValue() <= QtGlobalStatic::Destroyed; }
0073 bool exists() const noexcept { return guardValue() == QtGlobalStatic::Initialized; }
0074 operator Type *()
0075 {
0076 if (isDestroyed())
0077 return nullptr;
0078 return instance();
0079 }
0080 Type *operator()()
0081 {
0082 if (isDestroyed())
0083 return nullptr;
0084 return instance();
0085 }
0086 Type *operator->()
0087 {
0088 Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
0089 "The global static was used after being destroyed");
0090 return instance();
0091 }
0092 Type &operator*()
0093 {
0094 Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
0095 "The global static was used after being destroyed");
0096 return *instance();
0097 }
0098
0099 protected:
0100 static Type *instance() noexcept(Holder::ConstructionIsNoexcept)
0101 {
0102 static Holder holder;
0103 return holder.pointer();
0104 }
0105 static QtGlobalStatic::GuardValues guardValue() noexcept
0106 {
0107 return QtGlobalStatic::GuardValues(Holder::guard.loadAcquire());
0108 }
0109 };
0110
0111 #define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
0112 QT_WARNING_PUSH \
0113 QT_WARNING_DISABLE_CLANG("-Wunevaluated-expression") \
0114 namespace { struct Q_QGS_ ## NAME { \
0115 typedef TYPE QGS_Type; \
0116 static void innerFunction(void *pointer) \
0117 noexcept(noexcept(std::remove_cv_t<QGS_Type> ARGS)) \
0118 { \
0119 new (pointer) QGS_Type ARGS; \
0120 } \
0121 }; } \
0122 Q_CONSTINIT static QGlobalStatic<QtGlobalStatic::Holder<Q_QGS_ ## NAME>> NAME; \
0123 QT_WARNING_POP
0124
0125
0126 #define Q_GLOBAL_STATIC(TYPE, NAME, ...) \
0127 Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, (__VA_ARGS__))
0128
0129 QT_END_NAMESPACE
0130 #endif