Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:09:07

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 #if 0
0015 #pragma qt_class(QApplicationStatic)
0016 #endif
0017 
0018 QT_BEGIN_NAMESPACE
0019 
0020 namespace QtGlobalStatic {
0021 template <typename QAS> struct ApplicationHolder
0022 {
0023     using Type = typename QAS::QAS_Type;
0024     using PlainType = std::remove_cv_t<Type>;
0025 
0026     Q_CONSTINIT static inline struct { alignas(Type) unsigned char data[sizeof(Type)]; } storage = {};
0027     Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
0028     Q_CONSTINIT static inline QBasicMutex mutex {};
0029 
0030     static constexpr bool MutexLockIsNoexcept = noexcept(mutex.lock());
0031     static constexpr bool ConstructionIsNoexcept = noexcept(QAS::innerFunction(nullptr));
0032 
0033     ApplicationHolder() = default;
0034     Q_DISABLE_COPY_MOVE(ApplicationHolder)
0035     ~ApplicationHolder()
0036     {
0037         if (guard.loadAcquire() == QtGlobalStatic::Initialized) {
0038             // No mutex! Up to external code to ensure no race happens.
0039             guard.storeRelease(QtGlobalStatic::Destroyed);
0040             realPointer()->~PlainType();
0041         }
0042     }
0043 
0044     static PlainType *realPointer()
0045     {
0046         return std::launder(reinterpret_cast<PlainType *>(&storage));
0047     }
0048 
0049     // called from QGlobalStatic::instance()
0050     PlainType *pointer() noexcept(MutexLockIsNoexcept && ConstructionIsNoexcept)
0051     {
0052         if (guard.loadAcquire() == QtGlobalStatic::Initialized)
0053             return realPointer();
0054         QMutexLocker locker(&mutex);
0055         if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) {
0056             QAS::innerFunction(&storage);
0057             const auto *app = QCoreApplication::instance();
0058             Q_ASSERT_X(app, Q_FUNC_INFO,
0059                        "The application static was used without a QCoreApplication instance");
0060             QObject::connect(app, &QObject::destroyed, app, reset, Qt::DirectConnection);
0061             guard.storeRelease(QtGlobalStatic::Initialized);
0062         }
0063         return realPointer();
0064     }
0065 
0066     static void reset()
0067     {
0068         // we only synchronize using the mutex here, not the guard
0069         QMutexLocker locker(&mutex);
0070         realPointer()->~PlainType();
0071         guard.storeRelaxed(QtGlobalStatic::Uninitialized);
0072     }
0073 };
0074 } // namespace QtGlobalStatic
0075 
0076 #define Q_APPLICATION_STATIC(TYPE, NAME, ...) \
0077     namespace { struct Q_QAS_ ## NAME {                                     \
0078         typedef TYPE QAS_Type;                                              \
0079         static void innerFunction(void *pointer)                            \
0080             noexcept(noexcept(std::remove_cv_t<QAS_Type>(__VA_ARGS__)))     \
0081         {                                                                   \
0082             new (pointer) QAS_Type(__VA_ARGS__);                            \
0083         }                                                                   \
0084     }; }                                                                    \
0085     static QGlobalStatic<QtGlobalStatic::ApplicationHolder<Q_QAS_ ## NAME>> NAME;\
0086     /**/
0087 
0088 QT_END_NAMESPACE
0089 
0090 #endif // QAPPLICATIONSTATIC_H