1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
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 #ifndef QTHREADSTORAGE_H
41 #define QTHREADSTORAGE_H
42
43 #include <QtCore/qglobal.h>
44
45 #if QT_CONFIG(thread)
46
47 QT_BEGIN_NAMESPACE
48
49
50 class Q_CORE_EXPORT QThreadStorageData
51 {
52 public:
53 explicit QThreadStorageData(void (*func)(void *));
54 ~QThreadStorageData();
55
56 void** get() const;
57 void** set(void* p);
58
59 static void finish(void**);
60 int id;
61 };
62
63 #if !defined(QT_MOC_CPP)
64 // MOC_SKIP_BEGIN
65
66 // pointer specialization
67 template <typename T>
68 inline
qThreadStorage_localData(QThreadStorageData & d,T **)69 T *&qThreadStorage_localData(QThreadStorageData &d, T **)
70 {
71 void **v = d.get();
72 if (!v) v = d.set(nullptr);
73 return *(reinterpret_cast<T**>(v));
74 }
75
76 template <typename T>
77 inline
qThreadStorage_localData_const(const QThreadStorageData & d,T **)78 T *qThreadStorage_localData_const(const QThreadStorageData &d, T **)
79 {
80 void **v = d.get();
81 return v ? *(reinterpret_cast<T**>(v)) : 0;
82 }
83
84 template <typename T>
85 inline
qThreadStorage_setLocalData(QThreadStorageData & d,T ** t)86 void qThreadStorage_setLocalData(QThreadStorageData &d, T **t)
87 { (void) d.set(*t); }
88
89 template <typename T>
90 inline
qThreadStorage_deleteData(void * d,T **)91 void qThreadStorage_deleteData(void *d, T **)
92 { delete static_cast<T *>(d); }
93
94 // value-based specialization
95 template <typename T>
96 inline
qThreadStorage_localData(QThreadStorageData & d,T *)97 T &qThreadStorage_localData(QThreadStorageData &d, T *)
98 {
99 void **v = d.get();
100 if (!v) v = d.set(new T());
101 return *(reinterpret_cast<T*>(*v));
102 }
103
104 template <typename T>
105 inline
qThreadStorage_localData_const(const QThreadStorageData & d,T *)106 T qThreadStorage_localData_const(const QThreadStorageData &d, T *)
107 {
108 void **v = d.get();
109 return v ? *(reinterpret_cast<T*>(*v)) : T();
110 }
111
112 template <typename T>
113 inline
qThreadStorage_setLocalData(QThreadStorageData & d,T * t)114 void qThreadStorage_setLocalData(QThreadStorageData &d, T *t)
115 { (void) d.set(new T(*t)); }
116
117 template <typename T>
118 inline
qThreadStorage_deleteData(void * d,T *)119 void qThreadStorage_deleteData(void *d, T *)
120 { delete static_cast<T *>(d); }
121
122
123 // MOC_SKIP_END
124 #endif
125
126 template <class T>
127 class QThreadStorage
128 {
129 private:
130 QThreadStorageData d;
131
Q_DISABLE_COPY(QThreadStorage)132 Q_DISABLE_COPY(QThreadStorage)
133
134 static inline void deleteData(void *x)
135 { qThreadStorage_deleteData(x, reinterpret_cast<T*>(0)); }
136
137 public:
QThreadStorage()138 inline QThreadStorage() : d(deleteData) { }
~QThreadStorage()139 inline ~QThreadStorage() { }
140
hasLocalData()141 inline bool hasLocalData() const
142 { return d.get() != nullptr; }
143
localData()144 inline T& localData()
145 { return qThreadStorage_localData(d, reinterpret_cast<T*>(0)); }
localData()146 inline T localData() const
147 { return qThreadStorage_localData_const(d, reinterpret_cast<T*>(0)); }
148
setLocalData(T t)149 inline void setLocalData(T t)
150 { qThreadStorage_setLocalData(d, &t); }
151 };
152
153 QT_END_NAMESPACE
154
155 #else // !QT_CONFIG(thread)
156
157 #include <QtCore/qscopedpointer.h>
158
159 #include <type_traits>
160
161 template <typename T, typename U>
162 inline bool qThreadStorage_hasLocalData(const QScopedPointer<T, U> &data)
163 {
164 return !!data;
165 }
166
167 template <typename T, typename U>
168 inline bool qThreadStorage_hasLocalData(const QScopedPointer<T*, U> &data)
169 {
170 return !!data ? *data != nullptr : false;
171 }
172
173 template <typename T>
174 inline void qThreadStorage_deleteLocalData(T *t)
175 {
176 delete t;
177 }
178
179 template <typename T>
180 inline void qThreadStorage_deleteLocalData(T **t)
181 {
182 delete *t;
183 delete t;
184 }
185
186 template <class T>
187 class QThreadStorage
188 {
189 private:
190 struct ScopedPointerThreadStorageDeleter
191 {
192 static inline void cleanup(T *t)
193 {
194 if (t == nullptr)
195 return;
196 qThreadStorage_deleteLocalData(t);
197 }
198 };
199 QScopedPointer<T, ScopedPointerThreadStorageDeleter> data;
200
201 public:
202 QThreadStorage() = default;
203 ~QThreadStorage() = default;
204 QThreadStorage(const QThreadStorage &rhs) = delete;
205 QThreadStorage &operator=(const QThreadStorage &rhs) = delete;
206
207 inline bool hasLocalData() const
208 {
209 return qThreadStorage_hasLocalData(data);
210 }
211
212 inline T& localData()
213 {
214 if (!data)
215 data.reset(new T());
216 return *data;
217 }
218
219 inline T localData() const
220 {
221 return !!data ? *data : T();
222 }
223
224 inline void setLocalData(T t)
225 {
226 data.reset(new T(t));
227 }
228 };
229
230 #endif // QT_CONFIG(thread)
231
232 #endif // QTHREADSTORAGE_H
233