1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QAPPLICATIONSTATIC_H
6#define QAPPLICATIONSTATIC_H
7
8#include <QtCore/QMutex>
9#include <QtCore/qcoreapplication.h>
10#include <QtCore/qglobalstatic.h>
11
12#include <new>
13
14#if 0
15#pragma qt_class(QApplicationStatic)
16#endif
17
18QT_BEGIN_NAMESPACE
19
20namespace QtGlobalStatic {
21template <typename QAS> struct ApplicationHolder
22{
23 using Type = typename QAS::QAS_Type;
24 using PlainType = std::remove_cv_t<Type>;
25
26 Q_CONSTINIT static inline struct { alignas(Type) unsigned char data[sizeof(Type)]; } storage = {};
27 Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
28 Q_CONSTINIT static inline QBasicMutex mutex {};
29
30 static constexpr bool MutexLockIsNoexcept = noexcept(mutex.lock());
31 static constexpr bool ConstructionIsNoexcept = noexcept(QAS::innerFunction(nullptr));
32
33 ApplicationHolder() = default;
34 Q_DISABLE_COPY_MOVE(ApplicationHolder)
35 ~ApplicationHolder()
36 {
37 if (guard.loadAcquire() == QtGlobalStatic::Initialized) {
38 // No mutex! Up to external code to ensure no race happens.
39 guard.storeRelease(newValue: QtGlobalStatic::Destroyed);
40 realPointer()->~PlainType();
41 }
42 }
43
44 static PlainType *realPointer()
45 {
46 return std::launder(reinterpret_cast<PlainType *>(&storage));
47 }
48
49 // called from QGlobalStatic::instance()
50 PlainType *pointer() noexcept(MutexLockIsNoexcept && ConstructionIsNoexcept)
51 {
52 if (guard.loadAcquire() == QtGlobalStatic::Initialized)
53 return realPointer();
54 QMutexLocker locker(&mutex);
55 if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) {
56 QAS::innerFunction(&storage);
57 const auto *app = QCoreApplication::instance();
58 Q_ASSERT_X(app, Q_FUNC_INFO,
59 "The application static was used without a QCoreApplication instance");
60 QObject::connect(app, &QObject::destroyed, app, reset, Qt::DirectConnection);
61 guard.storeRelease(newValue: QtGlobalStatic::Initialized);
62 }
63 return realPointer();
64 }
65
66 static void reset()
67 {
68 // we only synchronize using the mutex here, not the guard
69 QMutexLocker locker(&mutex);
70 realPointer()->~PlainType();
71 guard.storeRelaxed(newValue: QtGlobalStatic::Uninitialized);
72 }
73};
74} // namespace QtGlobalStatic
75
76#define Q_APPLICATION_STATIC(TYPE, NAME, ...) \
77 namespace { struct Q_QAS_ ## NAME { \
78 typedef TYPE QAS_Type; \
79 static void innerFunction(void *pointer) \
80 noexcept(noexcept(std::remove_cv_t<QAS_Type>(__VA_ARGS__))) \
81 { \
82 new (pointer) QAS_Type(__VA_ARGS__); \
83 } \
84 }; } \
85 static QGlobalStatic<QtGlobalStatic::ApplicationHolder<Q_QAS_ ## NAME>> NAME;\
86 /**/
87
88QT_END_NAMESPACE
89
90#endif // QAPPLICATIONSTATIC_H
91

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/corelib/kernel/qapplicationstatic.h