Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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// Qt-Security score:significant reason:default
4
5#ifndef QGLOBALSTATIC_H
6#define QGLOBALSTATIC_H
7
8#include <QtCore/qassert.h>
9#include <QtCore/qatomic.h>
10#include <QtCore/qtclasshelpermacros.h>
11
12#include <atomic> // for bootstrapped (no thread) builds
13#include <type_traits>
14
15QT_BEGIN_NAMESPACE
16
17namespace QtGlobalStatic {
24
25template <typename QGS> union Holder
26{
27 using Type = typename QGS::QGS_Type;
29
30 static constexpr bool ConstructionIsNoexcept = noexcept(QGS::innerFunction(nullptr));
32
33 // union's sole member
35
37 {
38 QGS::innerFunction(pointer());
39 guard.storeRelaxed(QtGlobalStatic::Initialized);
40 }
41
43 {
44 // TSAN does not support atomic_thread_fence and GCC complains:
45 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97868
46 // https://github.com/google/sanitizers/issues/1352
47 // QTBUG-134415
48QT_WARNING_PUSH
49#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1100
50QT_WARNING_DISABLE_GCC("-Wtsan")
51#endif
52 // import changes to *pointer() by other threads before running ~PlainType():
53 std::atomic_thread_fence(std::memory_order_acquire);
54QT_WARNING_POP
55 pointer()->~PlainType();
56 guard.storeRelease(QtGlobalStatic::Destroyed);
57 }
58
59 PlainType *pointer() noexcept
60 {
61 return &storage;
62 }
63
65};
66}
67
68template <typename Holder> struct QGlobalStatic
69{
70 using Type = typename Holder::Type;
71
72 bool isDestroyed() const noexcept { return guardValue() <= QtGlobalStatic::Destroyed; }
73 bool exists() const noexcept { return guardValue() == QtGlobalStatic::Initialized; }
75 {
76 if (isDestroyed())
77 return nullptr;
78 return instance();
79 }
81 {
82 if (isDestroyed())
83 return nullptr;
84 return instance();
85 }
87 {
88 Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
89 "The global static was used after being destroyed");
90 return instance();
91 }
93 {
94 Q_ASSERT_X(!isDestroyed(), Q_FUNC_INFO,
95 "The global static was used after being destroyed");
96 return *instance();
97 }
98
99protected:
101 {
102 static Holder holder;
103 return holder.pointer();
104 }
106 {
107 return QtGlobalStatic::GuardValues(Holder::guard.loadAcquire());
108 }
109};
110
111#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
112 QT_WARNING_PUSH
113 QT_WARNING_DISABLE_CLANG("-Wunevaluated-expression")
114 namespace { struct Q_QGS_ ## NAME {
115 typedef TYPE QGS_Type;
116 static void innerFunction(void *pointer)
117 noexcept(noexcept(std::remove_cv_t<QGS_Type> ARGS))
118 {
119 new (pointer) QGS_Type ARGS;
120 }
121 }; }
122 Q_CONSTINIT static QGlobalStatic<QtGlobalStatic::Holder<Q_QGS_ ## NAME>> NAME;
123 QT_WARNING_POP
124 /**/
125
126#define Q_GLOBAL_STATIC(TYPE, NAME, ...)
127 Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, (__VA_ARGS__))
128
129QT_END_NAMESPACE
130#endif // QGLOBALSTATIC_H
\inmodule QtCore
Definition qhash.h:843
\inmodule QtCore \inheaderfile QPermissions
void requestPermission(const QPermission &permission, const PermissionCallback &callback)
Qt::PermissionStatus checkPermission(const QPermission &permission)
Definition qcompare.h:111
PermissionStatus
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define QStringLiteral(str)
Definition qstring.h:1825
Type * operator()()
Type & operator*()
typename Holder::Type Type
static Type * instance() noexcept(Holder::ConstructionIsNoexcept)
static QtGlobalStatic::GuardValues guardValue() noexcept
bool exists() const noexcept
Type * operator->()
bool isDestroyed() const noexcept
PlainType * pointer() noexcept
static constexpr bool ConstructionIsNoexcept
Holder() noexcept(ConstructionIsNoexcept)
typename QGS::QGS_Type Type