Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:15

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // Copyright (C) 2021 Intel Corporation.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QAPPLICATIONSTATIC_H
0006 #define QAPPLICATIONSTATIC_H
0007 
0008 #include <QtCore/QMutex>
0009 #include <QtCore/qcoreapplication.h>
0010 #include <QtCore/qglobalstatic.h>
0011 
0012 #include <new>
0013 
0014 QT_BEGIN_NAMESPACE
0015 
0016 namespace QtGlobalStatic {
0017 template <typename QAS> struct ApplicationHolder
0018 {
0019     using Type = typename QAS::QAS_Type;
0020     using PlainType = std::remove_cv_t<Type>;
0021 
0022     Q_CONSTINIT static inline struct { alignas(Type) unsigned char data[sizeof(Type)]; } storage = {};
0023     Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
0024     Q_CONSTINIT static inline QBasicMutex mutex {};
0025 
0026     static constexpr bool MutexLockIsNoexcept = noexcept(mutex.lock());
0027     static constexpr bool ConstructionIsNoexcept = noexcept(QAS::innerFunction(nullptr));
0028 
0029     ApplicationHolder() = default;
0030     Q_DISABLE_COPY_MOVE(ApplicationHolder)
0031     ~ApplicationHolder()
0032     {
0033         if (guard.loadAcquire() == QtGlobalStatic::Initialized) {
0034             // No mutex! Up to external code to ensure no race happens.
0035             guard.storeRelease(QtGlobalStatic::Destroyed);
0036             realPointer()->~PlainType();
0037         }
0038     }
0039 
0040     static PlainType *realPointer()
0041     {
0042         return std::launder(reinterpret_cast<PlainType *>(&storage));
0043     }
0044 
0045     // called from QGlobalStatic::instance()
0046     PlainType *pointer() noexcept(MutexLockIsNoexcept && ConstructionIsNoexcept)
0047     {
0048         if (guard.loadAcquire() == QtGlobalStatic::Initialized)
0049             return realPointer();
0050         QMutexLocker locker(&mutex);
0051         if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) {
0052             QAS::innerFunction(&storage);
0053             const auto *app = QCoreApplication::instance();
0054             Q_ASSERT_X(app, Q_FUNC_INFO,
0055                        "The application static was used without a QCoreApplication instance");
0056             QObject::connect(app, &QObject::destroyed, app, reset, Qt::DirectConnection);
0057             guard.storeRelease(QtGlobalStatic::Initialized);
0058         }
0059         return realPointer();
0060     }
0061 
0062     static void reset()
0063     {
0064         // we only synchronize using the mutex here, not the guard
0065         QMutexLocker locker(&mutex);
0066         realPointer()->~PlainType();
0067         guard.storeRelaxed(QtGlobalStatic::Uninitialized);
0068     }
0069 };
0070 } // namespace QtGlobalStatic
0071 
0072 #define Q_APPLICATION_STATIC(TYPE, NAME, ...) \
0073     namespace { struct Q_QAS_ ## NAME {                                     \
0074         typedef TYPE QAS_Type;                                              \
0075         static void innerFunction(void *pointer)                            \
0076             noexcept(noexcept(std::remove_cv_t<QAS_Type>(__VA_ARGS__)))     \
0077         {                                                                   \
0078             new (pointer) QAS_Type(__VA_ARGS__);                            \
0079         }                                                                   \
0080     }; }                                                                    \
0081     static QGlobalStatic<QtGlobalStatic::ApplicationHolder<Q_QAS_ ## NAME>> NAME;\
0082     /**/
0083 
0084 QT_END_NAMESPACE
0085 
0086 #endif // QAPPLICATIONSTATIC_H