Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qglobalstatic.h
Go to the documentation of this file.
1// Copyright (C) 2021 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QGLOBALSTATIC_H
5#define QGLOBALSTATIC_H
6
7#include <QtCore/qassert.h>
8#include <QtCore/qatomic.h>
9#include <QtCore/qtclasshelpermacros.h>
10
11#include <atomic> // for bootstrapped (no thread) builds
12#include <type_traits>
13
15
16namespace QtGlobalStatic {
23
24template <typename QGS> union Holder
25{
26 using Type = typename QGS::QGS_Type;
27 using PlainType = std::remove_cv_t<Type>;
28
29 static constexpr bool ConstructionIsNoexcept = noexcept(QGS::innerFunction(nullptr));
30 Q_CONSTINIT static inline QBasicAtomicInteger<qint8> guard = { QtGlobalStatic::Uninitialized };
31
32 // union's sole member
34
36 {
37 QGS::innerFunction(pointer());
39 }
40
42 {
43 // TSAN does not support atomic_thread_fence and GCC complains:
44 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97868
45 // https://github.com/google/sanitizers/issues/1352
47#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
49#endif
50 // import changes to *pointer() by other threads before running ~PlainType():
51 std::atomic_thread_fence(std::memory_order_acquire);
53 pointer()->~PlainType();
54 guard.storeRelease(QtGlobalStatic::Destroyed);
55 }
56
57 PlainType *pointer() noexcept
58 {
59 return &storage;
60 }
61
62 Q_DISABLE_COPY_MOVE(Holder)
63};
64}
65
66template <typename Holder> struct QGlobalStatic
67{
68 using Type = typename Holder::Type;
69
70 bool isDestroyed() const noexcept { return guardValue() <= QtGlobalStatic::Destroyed; }
71 bool exists() const noexcept { return guardValue() == QtGlobalStatic::Initialized; }
72 operator Type *()
73 {
74 if (isDestroyed())
75 return nullptr;
76 return instance();
77 }
79 {
80 if (isDestroyed())
81 return nullptr;
82 return instance();
83 }
85 {
87 "The global static was used after being destroyed");
88 return instance();
89 }
91 {
93 "The global static was used after being destroyed");
94 return *instance();
95 }
96
97protected:
98 static Type *instance() noexcept(Holder::ConstructionIsNoexcept)
99 {
100 static Holder holder;
101 return holder.pointer();
102 }
104 {
105 return QtGlobalStatic::GuardValues(Holder::guard.loadAcquire());
106 }
107};
108
109#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
110 QT_WARNING_PUSH \
111 QT_WARNING_DISABLE_CLANG("-Wunevaluated-expression") \
112 namespace { struct Q_QGS_ ## NAME { \
113 typedef TYPE QGS_Type; \
114 static void innerFunction(void *pointer) \
115 noexcept(noexcept(std::remove_cv_t<QGS_Type> ARGS)) \
116 { \
117 new (pointer) QGS_Type ARGS; \
118 } \
119 }; } \
120 Q_CONSTINIT static QGlobalStatic<QtGlobalStatic::Holder<Q_QGS_ ## NAME>> NAME; \
121 QT_WARNING_POP
122
123
124#define Q_GLOBAL_STATIC(TYPE, NAME, ...) \
125 Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, (__VA_ARGS__))
126
128#endif // QGLOBALSTATIC_H
Combined button and popup list for selecting options.
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_GCC(text)
#define Q_FUNC_INFO
#define QT_WARNING_PUSH
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
Type * operator()()
Type & operator*()
static Type * instance() noexcept(Holder::ConstructionIsNoexcept)
static QtGlobalStatic::GuardValues guardValue() noexcept
bool exists() const noexcept
Type * operator->()
bool isDestroyed() const noexcept
Definition moc.h:23
PlainType * pointer() noexcept
static constexpr bool ConstructionIsNoexcept
Holder() noexcept(ConstructionIsNoexcept)
static Q_CONSTINIT QBasicAtomicInteger< qint8 > guard
std::remove_cv_t< Type > PlainType