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 QSHAREDDATA_H
41 #define QSHAREDDATA_H
42
43 #include <QtCore/qglobal.h>
44 #include <QtCore/qatomic.h>
45 #if QT_DEPRECATED_SINCE(5, 6)
46 #include <QtCore/qhash.h>
47 #endif
48 #include <QtCore/qhashfunctions.h>
49
50 QT_BEGIN_NAMESPACE
51
52
53 template <class T> class QSharedDataPointer;
54
55 class
56 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
57 Q_CORE_EXPORT
58 #endif
59 QSharedData
60 {
61 public:
62 mutable QAtomicInt ref;
63
QSharedData()64 inline QSharedData() noexcept : ref(0) { }
QSharedData(const QSharedData &)65 inline QSharedData(const QSharedData &) noexcept : ref(0) { }
66
67 // using the assignment operator would lead to corruption in the ref-counting
68 QSharedData &operator=(const QSharedData &) = delete;
69 ~QSharedData() = default;
70 };
71
72 template <class T> class QSharedDataPointer
73 {
74 public:
75 typedef T Type;
76 typedef T *pointer;
77
detach()78 inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
79 inline T &operator*() { detach(); return *d; }
80 inline const T &operator*() const { return *d; }
81 inline T *operator->() { detach(); return d; }
82 inline const T *operator->() const { return d; }
83 inline operator T *() { detach(); return d; }
84 inline operator const T *() const { return d; }
data()85 inline T *data() { detach(); return d; }
data()86 inline const T *data() const { return d; }
constData()87 inline const T *constData() const { return d; }
88
89 inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; }
90 inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; }
91
QSharedDataPointer()92 inline QSharedDataPointer() { d = nullptr; }
~QSharedDataPointer()93 inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
94
95 explicit QSharedDataPointer(T *data) noexcept;
QSharedDataPointer(const QSharedDataPointer<T> & o)96 inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
97 inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) {
98 if (o.d != d) {
99 if (o.d)
100 o.d->ref.ref();
101 T *old = d;
102 d = o.d;
103 if (old && !old->ref.deref())
104 delete old;
105 }
106 return *this;
107 }
108 inline QSharedDataPointer &operator=(T *o) {
109 if (o != d) {
110 if (o)
111 o->ref.ref();
112 T *old = d;
113 d = o;
114 if (old && !old->ref.deref())
115 delete old;
116 }
117 return *this;
118 }
QSharedDataPointer(QSharedDataPointer && o)119 QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
120 inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) noexcept
121 {
122 QSharedDataPointer moved(std::move(other));
123 swap(moved);
124 return *this;
125 }
126
127 inline bool operator!() const { return !d; }
128
swap(QSharedDataPointer & other)129 inline void swap(QSharedDataPointer &other) noexcept
130 { qSwap(d, other.d); }
131
132 protected:
133 T *clone();
134
135 private:
136 void detach_helper();
137
138 T *d;
139 };
140
141 template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2)
142 {
143 Q_UNUSED(p1);
144 return !p2;
145 }
146
147 template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2)
148 {
149 Q_UNUSED(p2);
150 return !p1;
151 }
152
153 template <class T> class QExplicitlySharedDataPointer
154 {
155 public:
156 typedef T Type;
157 typedef T *pointer;
158
159 inline T &operator*() const { return *d; }
160 inline T *operator->() { return d; }
161 inline T *operator->() const { return d; }
data()162 inline T *data() const { return d; }
constData()163 inline const T *constData() const { return d; }
take()164 inline T *take() { T *x = d; d = nullptr; return x; }
165
detach()166 inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
167
reset()168 inline void reset()
169 {
170 if(d && !d->ref.deref())
171 delete d;
172
173 d = nullptr;
174 }
175
176 inline operator bool () const { return d != nullptr; }
177
178 inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; }
179 inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; }
180 inline bool operator==(const T *ptr) const { return d == ptr; }
181 inline bool operator!=(const T *ptr) const { return d != ptr; }
182
QExplicitlySharedDataPointer()183 inline QExplicitlySharedDataPointer() { d = nullptr; }
~QExplicitlySharedDataPointer()184 inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
185
186 explicit QExplicitlySharedDataPointer(T *data) noexcept;
QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> & o)187 inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
188
189 template<class X>
QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> & o)190 inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o)
191 #ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
192 : d(static_cast<T *>(o.data()))
193 #else
194 : d(o.data())
195 #endif
196 {
197 if(d)
198 d->ref.ref();
199 }
200
201 inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) {
202 if (o.d != d) {
203 if (o.d)
204 o.d->ref.ref();
205 T *old = d;
206 d = o.d;
207 if (old && !old->ref.deref())
208 delete old;
209 }
210 return *this;
211 }
212 inline QExplicitlySharedDataPointer &operator=(T *o) {
213 if (o != d) {
214 if (o)
215 o->ref.ref();
216 T *old = d;
217 d = o;
218 if (old && !old->ref.deref())
219 delete old;
220 }
221 return *this;
222 }
QExplicitlySharedDataPointer(QExplicitlySharedDataPointer && o)223 inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
224 inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) noexcept
225 {
226 QExplicitlySharedDataPointer moved(std::move(other));
227 swap(moved);
228 return *this;
229 }
230
231 inline bool operator!() const { return !d; }
232
swap(QExplicitlySharedDataPointer & other)233 inline void swap(QExplicitlySharedDataPointer &other) noexcept
234 { qSwap(d, other.d); }
235
236 protected:
237 T *clone();
238
239 private:
240 void detach_helper();
241
242 T *d;
243 };
244
245 template <class T>
QSharedDataPointer(T * adata)246 Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) noexcept
247 : d(adata)
248 { if (d) d->ref.ref(); }
249
250 template <class T>
clone()251 Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
252 {
253 return new T(*d);
254 }
255
256 template <class T>
detach_helper()257 Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
258 {
259 T *x = clone();
260 x->ref.ref();
261 if (!d->ref.deref())
262 delete d;
263 d = x;
264 }
265
266 template <class T>
clone()267 Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
268 {
269 return new T(*d);
270 }
271
272 template <class T>
detach_helper()273 Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
274 {
275 T *x = clone();
276 x->ref.ref();
277 if (!d->ref.deref())
278 delete d;
279 d = x;
280 }
281
282 template <class T>
QExplicitlySharedDataPointer(T * adata)283 Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) noexcept
284 : d(adata)
285 { if (d) d->ref.ref(); }
286
287 template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2)
288 {
289 Q_UNUSED(p1);
290 return !p2;
291 }
292
293 template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2)
294 {
295 Q_UNUSED(p2);
296 return !p1;
297 }
298
299 template <class T>
swap(QSharedDataPointer<T> & p1,QSharedDataPointer<T> & p2)300 Q_INLINE_TEMPLATE void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
301 { p1.swap(p2); }
302
303 template <class T>
swap(QExplicitlySharedDataPointer<T> & p1,QExplicitlySharedDataPointer<T> & p2)304 Q_INLINE_TEMPLATE void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2)
305 { p1.swap(p2); }
306
307 template <class T>
308 Q_INLINE_TEMPLATE uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0) noexcept
309 {
310 return qHash(ptr.data(), seed);
311 }
312 template <class T>
313 Q_INLINE_TEMPLATE uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0) noexcept
314 {
315 return qHash(ptr.data(), seed);
316 }
317
318 template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
319 template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE);
320
321 QT_END_NAMESPACE
322
323 #endif // QSHAREDDATA_H
324