1/****************************************************************************
2**
3** Copyright (C) 2016 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 <type_traits>
48
49QT_BEGIN_NAMESPACE
50
51namespace QtGlobalStatic {
52enum GuardValues {
53 Destroyed = -2,
54 Initialized = -1,
55 Uninitialized = 0,
56 Initializing = 1
57};
58}
59
60#if defined(Q_OS_UNIX) && defined(Q_CC_INTEL)
61// Work around Intel issue ID 6000058488:
62// local statics inside an inline function inside an anonymous namespace are global
63// symbols (this affects the IA-64 C++ ABI, so OS X and Linux only)
64# define Q_GLOBAL_STATIC_INTERNAL_DECORATION Q_DECL_HIDDEN
65#else
66# define Q_GLOBAL_STATIC_INTERNAL_DECORATION Q_DECL_HIDDEN inline
67#endif
68
69#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \
70 Q_GLOBAL_STATIC_INTERNAL_DECORATION Type *innerFunction() \
71 { \
72 struct HolderBase { \
73 HolderBase() = default; \
74 ~HolderBase() noexcept \
75 { if (guard.loadRelaxed() == QtGlobalStatic::Initialized) \
76 guard.storeRelaxed(QtGlobalStatic::Destroyed); } \
77 Q_DISABLE_COPY_MOVE(HolderBase) \
78 }; \
79 static struct Holder : public HolderBase { \
80 Type value; \
81 Holder() \
82 noexcept(noexcept(typename std::remove_cv<Type>::type ARGS)) \
83 : value ARGS \
84 { guard.storeRelaxed(QtGlobalStatic::Initialized); } \
85 } holder; \
86 return &holder.value; \
87 }
88
89
90// this class must be POD, unless the compiler supports thread-safe statics
91template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard>
92struct QGlobalStatic
93{
94 typedef T Type;
95
96 bool isDestroyed() const { return guard.loadRelaxed() <= QtGlobalStatic::Destroyed; }
97 bool exists() const { return guard.loadRelaxed() == QtGlobalStatic::Initialized; }
98 operator Type *()
99 {
100 if (isDestroyed())
101 return nullptr;
102 return innerFunction();
103 }
104 Type *operator()()
105 {
106 if (isDestroyed())
107 return nullptr;
108 return innerFunction();
109 }
110 Type *operator->()
111 {
112 Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC",
113 "The global static was used after being destroyed");
114 return innerFunction();
115 }
116 Type &operator*()
117 {
118 Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC",
119 "The global static was used after being destroyed");
120 return *innerFunction();
121 }
122};
123
124#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
125 namespace { namespace Q_QGS_ ## NAME { \
126 typedef TYPE Type; \
127 QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized); \
128 Q_GLOBAL_STATIC_INTERNAL(ARGS) \
129 } } \
130 static QGlobalStatic<TYPE, \
131 Q_QGS_ ## NAME::innerFunction, \
132 Q_QGS_ ## NAME::guard> NAME;
133
134#define Q_GLOBAL_STATIC(TYPE, NAME) \
135 Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
136
137QT_END_NAMESPACE
138#endif // QGLOBALSTATIC_H
139

source code of qtbase/src/corelib/global/qglobalstatic.h