Warning, file /include/QtCore/qglobalstatic.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
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 QT_WARNING_PUSH
0047 #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
0048 QT_WARNING_DISABLE_GCC("-Wtsan")
0049 #endif
0050
0051 std::atomic_thread_fence(std::memory_order_acquire);
0052 QT_WARNING_POP
0053 pointer()->~PlainType();
0054 guard.storeRelease(QtGlobalStatic::Destroyed);
0055 }
0056
0057 PlainType *pointer() noexcept
0058 {
0059 return &storage;
0060 }
0061
0062 Q_DISABLE_COPY_MOVE(Holder)
0063 };
0064 }
0065
0066 template <typename Holder> struct QGlobalStatic
0067 {
0068 using Type = typename Holder::Type;
0069
0070 bool isDestroyed() const noexcept { return guardValue() <= QtGlobalStatic::Destroyed; }
0071 bool exists() const noexcept { return guardValue() == QtGlobalStatic::Initialized; }
0072 operator Type *()
0073 {
0074 if (isDestroyed())
0075 return nullptr;
0076 return instance();
0077 }
0078 Type *operator()()
0079 {
0080 if (isDestroyed())
0081 return nullptr;
0082 return instance();
0083 }
0084 Type *operator->()
0085 {
0086 Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
0087 "The global static was used after being destroyed");
0088 return instance();
0089 }
0090 Type &operator*()
0091 {
0092 Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
0093 "The global static was used after being destroyed");
0094 return *instance();
0095 }
0096
0097 protected:
0098 static Type *instance() noexcept(Holder::ConstructionIsNoexcept)
0099 {
0100 static Holder holder;
0101 return holder.pointer();
0102 }
0103 static QtGlobalStatic::GuardValues guardValue() noexcept
0104 {
0105 return QtGlobalStatic::GuardValues(Holder::guard.loadAcquire());
0106 }
0107 };
0108
0109 #define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
0110 QT_WARNING_PUSH \
0111 QT_WARNING_DISABLE_CLANG("-Wunevaluated-expression") \
0112 namespace { struct Q_QGS_ ## NAME { \
0113 typedef TYPE QGS_Type; \
0114 static void innerFunction(void *pointer) \
0115 noexcept(noexcept(std::remove_cv_t<QGS_Type> ARGS)) \
0116 { \
0117 new (pointer) QGS_Type ARGS; \
0118 } \
0119 }; } \
0120 Q_CONSTINIT static QGlobalStatic<QtGlobalStatic::Holder<Q_QGS_ ## NAME>> NAME; \
0121 QT_WARNING_POP
0122
0123
0124 #define Q_GLOBAL_STATIC(TYPE, NAME, ...) \
0125 Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, (__VA_ARGS__))
0126
0127 QT_END_NAMESPACE
0128 #endif