Back to home page

EIC code displayed by LXR

 
 

    


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 // 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 QT_WARNING_PUSH
0047 #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
0048 QT_WARNING_DISABLE_GCC("-Wtsan")
0049 #endif
0050         // import changes to *pointer() by other threads before running ~PlainType():
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 // QGLOBALSTATIC_H