Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-20 09:21:39

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