Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:04:26

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 
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     // union's sole member
0033     PlainType storage;
0034 
0035     Holder() noexcept(ConstructionIsNoexcept)
0036     {
0037         QGS::innerFunction(pointer());
0038         guard.storeRelaxed(QtGlobalStatic::Initialized);
0039     }
0040 
0041     ~Holder()
0042     {
0043         // TSAN does not support atomic_thread_fence and GCC complains:
0044         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97868
0045         // https://github.com/google/sanitizers/issues/1352
0046         // QTBUG-134415
0047 QT_WARNING_PUSH
0048 #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
0049 QT_WARNING_DISABLE_GCC("-Wtsan")
0050 #endif
0051         // import changes to *pointer() by other threads before running ~PlainType():
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 // QGLOBALSTATIC_H