Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-15 09:19:54

0001 // Copyright (C) 2021 Intel Corporation.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 // Qt-Security score:significant reason:default
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     // union's sole member
0034     PlainType storage;
0035 
0036     Holder() noexcept(ConstructionIsNoexcept)
0037     {
0038         QGS::innerFunction(pointer());
0039         guard.storeRelaxed(QtGlobalStatic::Initialized);
0040     }
0041 
0042     ~Holder()
0043     {
0044         // TSAN does not support atomic_thread_fence and GCC complains:
0045         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97868
0046         // https://github.com/google/sanitizers/issues/1352
0047         // QTBUG-134415
0048 QT_WARNING_PUSH
0049 #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
0050 QT_WARNING_DISABLE_GCC("-Wtsan")
0051 #endif
0052         // import changes to *pointer() by other threads before running ~PlainType():
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 // QGLOBALSTATIC_H