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
47QT_BEGIN_NAMESPACE
48
49
50class Q_CORE_EXPORT QThreadStorageData
51{
52public:
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
67template <typename T>
68inline
69T *&qThreadStorage_localData(QThreadStorageData &d, T **)
70{
71 void **v = d.get();
72 if (!v) v = d.set(0);
73 return *(reinterpret_cast<T**>(v));
74}
75
76template <typename T>
77inline
78T *qThreadStorage_localData_const(const QThreadStorageData &d, T **)
79{
80 void **v = d.get();
81 return v ? *(reinterpret_cast<T**>(v)) : 0;
82}
83
84template <typename T>
85inline
86void qThreadStorage_setLocalData(QThreadStorageData &d, T **t)
87{ (void) d.set(*t); }
88
89template <typename T>
90inline
91void qThreadStorage_deleteData(void *d, T **)
92{ delete static_cast<T *>(d); }
93
94// value-based specialization
95template <typename T>
96inline
97T &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
104template <typename T>
105inline
106T qThreadStorage_localData_const(const QThreadStorageData &d, T *)
107{
108 void **v = d.get();
109 return v ? *(reinterpret_cast<T*>(*v)) : T();
110}
111
112template <typename T>
113inline
114void qThreadStorage_setLocalData(QThreadStorageData &d, T *t)
115{ (void) d.set(new T(*t)); }
116
117template <typename T>
118inline
119void qThreadStorage_deleteData(void *d, T *)
120{ delete static_cast<T *>(d); }
121
122
123// MOC_SKIP_END
124#endif
125
126template <class T>
127class QThreadStorage
128{
129private:
130 QThreadStorageData d;
131
132 Q_DISABLE_COPY(QThreadStorage)
133
134 static inline void deleteData(void *x)
135 { qThreadStorage_deleteData(x, reinterpret_cast<T*>(0)); }
136
137public:
138 inline QThreadStorage() : d(deleteData) { }
139 inline ~QThreadStorage() { }
140
141 inline bool hasLocalData() const
142 { return d.get() != 0; }
143
144 inline T& localData()
145 { return qThreadStorage_localData(d, reinterpret_cast<T*>(0)); }
146 inline T localData() const
147 { return qThreadStorage_localData_const(d, reinterpret_cast<T*>(0)); }
148
149 inline void setLocalData(T t)
150 { qThreadStorage_setLocalData(d, &t); }
151};
152
153QT_END_NAMESPACE
154
155#else // !QT_CONFIG(thread)
156
157#include <QtCore/qscopedpointer.h>
158
159#include <type_traits>
160
161template <typename T, typename U>
162inline bool qThreadStorage_hasLocalData(const QScopedPointer<T, U> &data)
163{
164 return !!data;
165}
166
167template <typename T, typename U>
168inline bool qThreadStorage_hasLocalData(const QScopedPointer<T*, U> &data)
169{
170 return !!data ? *data != nullptr : false;
171}
172
173template <typename T>
174inline void qThreadStorage_deleteLocalData(T *t)
175{
176 delete t;
177}
178
179template <typename T>
180inline void qThreadStorage_deleteLocalData(T **t)
181{
182 delete *t;
183 delete t;
184}
185
186template <class T>
187class QThreadStorage
188{
189private:
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
201public:
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