QtBase  v6.3.1
qglobalstatic.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 Intel Corporation.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include <QtCore/qglobal.h>
41 
42 #ifndef QGLOBALSTATIC_H
43 #define QGLOBALSTATIC_H
44 
45 #include <QtCore/qatomic.h>
46 
47 #include <atomic> // for bootstrapped (no thread) builds
48 #include <type_traits>
49 
51 
52 namespace QtGlobalStatic {
54  Destroyed = -2,
57  Initializing = 1
58 };
59 
60 template <typename QGS> union Holder
61 {
62  using Type = typename QGS::QGS_Type;
63  using PlainType = std::remove_cv_t<Type>;
64 
65  static constexpr bool ConstructionIsNoexcept = noexcept(QGS::innerFunction(nullptr));
67 
68  // union's sole member
70 
72  {
73  QGS::innerFunction(pointer());
75  }
76 
78  {
79  pointer()->~PlainType();
80  std::atomic_thread_fence(std::memory_order_acquire); // avoid mixing stores to guard and *pointer()
82  }
83 
84  PlainType *pointer() noexcept
85  {
86  return &storage;
87  }
88 
90 };
91 }
92 
93 template <typename Holder> struct QGlobalStatic
94 {
95  using Type = typename Holder::Type;
96 
97  bool isDestroyed() const noexcept { return guardValue() <= QtGlobalStatic::Destroyed; }
98  bool exists() const noexcept { return guardValue() == QtGlobalStatic::Initialized; }
99  operator Type *()
100  {
101  if (isDestroyed())
102  return nullptr;
103  return instance();
104  }
106  {
107  if (isDestroyed())
108  return nullptr;
109  return instance();
110  }
112  {
113  Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC",
114  "The global static was used after being destroyed");
115  return instance();
116  }
118  {
119  Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC",
120  "The global static was used after being destroyed");
121  return *instance();
122  }
123 
124 protected:
125  static Type *instance() noexcept(Holder::ConstructionIsNoexcept)
126  {
127  static Holder holder;
128  return holder.pointer();
129  }
131  {
132  return QtGlobalStatic::GuardValues(Holder::guard.loadAcquire());
133  }
134 };
135 
136 #define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
137  QT_WARNING_PUSH \
138  QT_WARNING_DISABLE_CLANG("-Wunevaluated-expression") \
139  namespace { struct Q_QGS_ ## NAME { \
140  typedef TYPE QGS_Type; \
141  static void innerFunction(void *pointer) \
142  noexcept(noexcept(std::remove_cv_t<QGS_Type> ARGS)) \
143  { \
144  new (pointer) QGS_Type ARGS; \
145  } \
146  }; } \
147  static QGlobalStatic<QtGlobalStatic::Holder<Q_QGS_ ## NAME>> NAME; \
148  QT_WARNING_POP
149 
150 
151 #define Q_GLOBAL_STATIC(TYPE, NAME, ...) \
152  Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, (__VA_ARGS__))
153 
155 #endif // QGLOBALSTATIC_H
void storeRelaxed(T newValue) noexcept
Definition: qbasicatomic.h:91
auto it unsigned count const
Definition: hb-iter.hh:848
#define Q_DISABLE_COPY_MOVE(Class)
Definition: qglobal.h:519
#define Q_ASSERT_X(cond, x, msg)
Definition: qrandom.cpp:85
QDBusVariant Type
Type & operator*()
static QtGlobalStatic::GuardValues guardValue() noexcept
bool exists() const noexcept
Definition: qglobalstatic.h:98
Type * operator()()
Type * operator->()
static Type * instance() noexcept(Holder::ConstructionIsNoexcept)
bool isDestroyed() const noexcept
Definition: qglobalstatic.h:97
Definition: moc.h:48
static constexpr bool ConstructionIsNoexcept
Definition: qglobalstatic.h:65
Holder() noexcept(ConstructionIsNoexcept)
Definition: qglobalstatic.h:71
PlainType * pointer() noexcept
Definition: qglobalstatic.h:84
std::remove_cv_t< Type > PlainType
Definition: qglobalstatic.h:63
static QBasicAtomicInteger< qint8 > guard
Definition: qglobalstatic.h:66