Qt 6.x
The Qt SDK
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/qatomic.h>
8#include <QtCore/qtclasshelpermacros.h>
9
10#include <atomic> // for bootstrapped (no thread) builds
11#include <type_traits>
12
14
15namespace QtGlobalStatic {
20 Initializing = 1
21};
22
23template <typename QGS> union Holder
24{
25 using Type = typename QGS::QGS_Type;
26 using PlainType = std::remove_cv_t<Type>;
27
28 static constexpr bool ConstructionIsNoexcept = noexcept(QGS::innerFunction(nullptr));
30
31 // union's sole member
33
35 {
36 QGS::innerFunction(pointer());
38 }
39
41 {
42 pointer()->~PlainType();
43 std::atomic_thread_fence(std::memory_order_acquire); // avoid mixing stores to guard and *pointer()
45 }
46
47 PlainType *pointer() noexcept
48 {
49 return &storage;
50 }
51
52 Q_DISABLE_COPY_MOVE(Holder)
53};
54}
55
56template <typename Holder> struct QGlobalStatic
57{
58 using Type = typename Holder::Type;
59
60 bool isDestroyed() const noexcept { return guardValue() <= QtGlobalStatic::Destroyed; }
61 bool exists() const noexcept { return guardValue() == QtGlobalStatic::Initialized; }
62 operator Type *()
63 {
64 if (isDestroyed())
65 return nullptr;
66 return instance();
67 }
69 {
70 if (isDestroyed())
71 return nullptr;
72 return instance();
73 }
75 {
76 Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC",
77 "The global static was used after being destroyed");
78 return instance();
79 }
81 {
82 Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC",
83 "The global static was used after being destroyed");
84 return *instance();
85 }
86
87protected:
88 static Type *instance() noexcept(Holder::ConstructionIsNoexcept)
89 {
90 static Holder holder;
91 return holder.pointer();
92 }
94 {
95 return QtGlobalStatic::GuardValues(Holder::guard.loadAcquire());
96 }
97};
98
99#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
100 QT_WARNING_PUSH \
101 QT_WARNING_DISABLE_CLANG("-Wunevaluated-expression") \
102 namespace { struct Q_QGS_ ## NAME { \
103 typedef TYPE QGS_Type; \
104 static void innerFunction(void *pointer) \
105 noexcept(noexcept(std::remove_cv_t<QGS_Type> ARGS)) \
106 { \
107 new (pointer) QGS_Type ARGS; \
108 } \
109 }; } \
110 Q_CONSTINIT static QGlobalStatic<QtGlobalStatic::Holder<Q_QGS_ ## NAME>> NAME; \
111 QT_WARNING_POP
112
113
114#define Q_GLOBAL_STATIC(TYPE, NAME, ...) \
115 Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, (__VA_ARGS__))
116
118#endif // QGLOBALSTATIC_H
void storeRelaxed(T newValue) noexcept
Combined button and popup list for selecting options.
#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:24
PlainType * pointer() noexcept
static constexpr bool ConstructionIsNoexcept
Holder() noexcept(ConstructionIsNoexcept)
static Q_CONSTINIT QBasicAtomicInteger< qint8 > guard
std::remove_cv_t< Type > PlainType