blob: 345a8807487f8301ad319722c8dd45e0826223f0 (
plain)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 | // Copyright (C) 2021 The Qt Company Ltd.// Copyright (C) 2021 Intel Corporation.// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#ifndef QAPPLICATIONSTATIC_H#define QAPPLICATIONSTATIC_H#include <QtCore/QMutex>#include <QtCore/qcoreapplication.h>#include <QtCore/qglobalstatic.h>#include <new>#if 0#pragma qt_class(QApplicationStatic)#endif QT_BEGIN_NAMESPACE namespace QtGlobalStatic {template<typename QAS>struct ApplicationHolder {using Type = typename QAS::QAS_Type;using PlainType =std::remove_cv_t<Type>; Q_CONSTINIT staticinlinestruct{alignas(Type)unsigned char data[sizeof(Type)]; } storage = {}; Q_CONSTINIT staticinline QBasicAtomicInteger<qint8> guard = {QtGlobalStatic::Uninitialized }; Q_CONSTINIT staticinline QBasicMutex mutex {};staticconstexprbool MutexLockIsNoexcept =noexcept(mutex.lock());staticconstexprbool ConstructionIsNoexcept =noexcept(QAS::innerFunction(nullptr));ApplicationHolder() =default;Q_DISABLE_COPY_MOVE(ApplicationHolder)~ApplicationHolder(){if(guard.loadAcquire() ==QtGlobalStatic::Initialized) {// No mutex! Up to external code to ensure no race happens. guard.storeRelease(QtGlobalStatic::Destroyed);realPointer()->~PlainType();}}static PlainType *realPointer(){returnstd::launder(reinterpret_cast<PlainType *>(&storage));}// called from QGlobalStatic::instance() PlainType *pointer()noexcept(MutexLockIsNoexcept && ConstructionIsNoexcept){if(guard.loadAcquire() ==QtGlobalStatic::Initialized)returnrealPointer(); QMutexLocker locker(&mutex);if(guard.loadRelaxed() ==QtGlobalStatic::Uninitialized) {QAS::innerFunction(&storage);constauto*app =QCoreApplication::instance();Q_ASSERT_X(app, Q_FUNC_INFO,"The application static was used without a QCoreApplication instance");QObject::connect(app, &QObject::destroyed, app, reset,Qt::DirectConnection); guard.storeRelease(QtGlobalStatic::Initialized);}returnrealPointer();}static voidreset(){// we only synchronize using the mutex here, not the guard QMutexLocker locker(&mutex);realPointer()->~PlainType(); guard.storeRelaxed(QtGlobalStatic::Uninitialized);}};}// namespace QtGlobalStatic#define Q_APPLICATION_STATIC(TYPE, NAME, ...) \ namespace { struct Q_QAS_ ## NAME { \ typedef TYPE QAS_Type; \ static void innerFunction(void *pointer) \ noexcept(noexcept(std::remove_cv_t<QAS_Type>(__VA_ARGS__))) \ { \ new (pointer) QAS_Type(__VA_ARGS__); \ } \ }; } \ static QGlobalStatic<QtGlobalStatic::ApplicationHolder<Q_QAS_ ## NAME>> NAME;\/**/ QT_END_NAMESPACE #endif// QAPPLICATIONSTATIC_H
|