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