Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2016 The Qt Company Ltd.
4 : ** Copyright (C) 2016 Intel Corporation.
5 : ** Contact: https://www.qt.io/licensing/
6 : **
7 : ** This file is part of the QtCore module of the Qt Toolkit.
8 : **
9 : ** $QT_BEGIN_LICENSE:LGPL$
10 : ** Commercial License Usage
11 : ** Licensees holding valid commercial Qt licenses may use this file in
12 : ** accordance with the commercial license agreement provided with the
13 : ** Software or, alternatively, in accordance with the terms contained in
14 : ** a written agreement between you and The Qt Company. For licensing terms
15 : ** and conditions see https://www.qt.io/terms-conditions. For further
16 : ** information use the contact form at https://www.qt.io/contact-us.
17 : **
18 : ** GNU Lesser General Public License Usage
19 : ** Alternatively, this file may be used under the terms of the GNU Lesser
20 : ** General Public License version 3 as published by the Free Software
21 : ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 : ** packaging of this file. Please review the following information to
23 : ** ensure the GNU Lesser General Public License version 3 requirements
24 : ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 : **
26 : ** GNU General Public License Usage
27 : ** Alternatively, this file may be used under the terms of the GNU
28 : ** General Public License version 2.0 or (at your option) the GNU General
29 : ** Public license version 3 or any later version approved by the KDE Free
30 : ** Qt Foundation. The licenses are as published by the Free Software
31 : ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 : ** included in the packaging of this file. Please review the following
33 : ** information to ensure the GNU General Public License requirements will
34 : ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 : ** https://www.gnu.org/licenses/gpl-3.0.html.
36 : **
37 : ** $QT_END_LICENSE$
38 : **
39 : ****************************************************************************/
40 :
41 : #ifndef Q_QDOC
42 :
43 : #ifndef QSHAREDPOINTER_H
44 : #error Do not include qsharedpointer_impl.h directly
45 : #endif
46 :
47 : #if 0
48 : #pragma qt_sync_skip_header_check
49 : #pragma qt_sync_stop_processing
50 : #endif
51 :
52 : #if 0
53 : // These macros are duplicated here to make syncqt not complain a about
54 : // this header, as we have a "qt_sync_stop_processing" below, which in turn
55 : // is here because this file contains a template mess and duplicates the
56 : // classes found in qsharedpointer.h
57 : QT_BEGIN_NAMESPACE
58 : QT_END_NAMESPACE
59 : #pragma qt_sync_stop_processing
60 : #endif
61 :
62 : #include <new>
63 : #include <QtCore/qatomic.h>
64 : #include <QtCore/qobject.h> // for qobject_cast
65 : #if QT_DEPRECATED_SINCE(5, 6)
66 : #include <QtCore/qhash.h>
67 : #endif
68 : #include <QtCore/qhashfunctions.h>
69 :
70 : QT_BEGIN_NAMESPACE
71 :
72 :
73 : // Macro QSHAREDPOINTER_VERIFY_AUTO_CAST
74 : // generates a compiler error if the following construct isn't valid:
75 : // T *ptr1;
76 : // X *ptr2 = ptr1;
77 : //
78 : #ifdef QT_NO_DEBUG
79 : # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) qt_noop()
80 : #else
81 :
82 : template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
83 : # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) \
84 : qt_sharedpointer_cast_check<T>(static_cast<X *>(0))
85 : #endif
86 :
87 : //
88 : // forward declarations
89 : //
90 : template <class T> class QWeakPointer;
91 : template <class T> class QSharedPointer;
92 : template <class T> class QEnableSharedFromThis;
93 :
94 : class QVariant;
95 :
96 : template <class X, class T>
97 : QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
98 : template <class X, class T>
99 : QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
100 : template <class X, class T>
101 : QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
102 :
103 : #ifndef QT_NO_QOBJECT
104 : template <class X, class T>
105 : QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
106 : #endif
107 :
108 : namespace QtSharedPointer {
109 : template <class T> class ExternalRefCount;
110 :
111 : template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
112 :
113 : // used in debug mode to verify the reuse of pointers
114 : Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
115 : Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
116 :
117 : template <class T, typename Klass, typename RetVal>
118 : inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
119 : { (t->*memberDeleter)(); }
120 : template <class T, typename Deleter>
121 : inline void executeDeleter(T *t, Deleter d)
122 : { d(t); }
123 : struct NormalDeleter {};
124 :
125 : // this uses partial template specialization
126 : template <class T> struct RemovePointer;
127 : template <class T> struct RemovePointer<T *> { typedef T Type; };
128 : template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
129 : template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
130 :
131 : // This class is the d-pointer of QSharedPointer and QWeakPointer.
132 : //
133 : // It is a reference-counted reference counter. "strongref" is the inner
134 : // reference counter, and it tracks the lifetime of the pointer itself.
135 : // "weakref" is the outer reference counter and it tracks the lifetime of
136 : // the ExternalRefCountData object.
137 : //
138 : // The deleter is stored in the destroyer member and is always a pointer to
139 : // a static function in ExternalRefCountWithCustomDeleter or in
140 : // ExternalRefCountWithContiguousData
141 : struct ExternalRefCountData
142 : {
143 : typedef void (*DestroyerFn)(ExternalRefCountData *);
144 : QBasicAtomicInt weakref;
145 : QBasicAtomicInt strongref;
146 : DestroyerFn destroyer;
147 :
148 : inline ExternalRefCountData(DestroyerFn d)
149 : : destroyer(d)
150 : {
151 : strongref.store(1);
152 : weakref.store(1);
153 : }
154 : inline ExternalRefCountData(Qt::Initialization) { }
155 0 : ~ExternalRefCountData() { Q_ASSERT(!weakref.load()); Q_ASSERT(strongref.load() <= 0); }
156 :
157 : void destroy() { destroyer(this); }
158 :
159 : #ifndef QT_NO_QOBJECT
160 : Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
161 : Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
162 : Q_CORE_EXPORT void checkQObjectShared(const QObject *);
163 : #endif
164 : inline void checkQObjectShared(...) { }
165 : inline void setQObjectShared(...) { }
166 :
167 0 : inline void operator delete(void *ptr) { ::operator delete(ptr); }
168 : inline void operator delete(void *, void *) { }
169 : };
170 : // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
171 :
172 : template <class T, typename Deleter>
173 : struct CustomDeleter
174 : {
175 : Deleter deleter;
176 : T *ptr;
177 :
178 : CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
179 : void execute() { executeDeleter(ptr, deleter); }
180 : };
181 : // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
182 : // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
183 : // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
184 : // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
185 :
186 : // This specialization of CustomDeleter for a deleter of type NormalDeleter
187 : // is an optimization: instead of storing a pointer to a function that does
188 : // the deleting, we simply delete the pointer ourselves.
189 : template <class T>
190 : struct CustomDeleter<T, NormalDeleter>
191 : {
192 : T *ptr;
193 :
194 : CustomDeleter(T *p, NormalDeleter) : ptr(p) {}
195 : void execute() { delete ptr; }
196 : };
197 : // sizeof(CustomDeleter specialization) = sizeof(void*)
198 :
199 : // This class extends ExternalRefCountData and implements
200 : // the static function that deletes the object. The pointer and the
201 : // custom deleter are kept in the "extra" member so we can construct
202 : // and destruct it independently of the full structure.
203 : template <class T, typename Deleter>
204 : struct ExternalRefCountWithCustomDeleter: public ExternalRefCountData
205 : {
206 : typedef ExternalRefCountWithCustomDeleter Self;
207 : typedef ExternalRefCountData BaseClass;
208 : CustomDeleter<T, Deleter> extra;
209 :
210 : static inline void deleter(ExternalRefCountData *self)
211 : {
212 : Self *realself = static_cast<Self *>(self);
213 : realself->extra.execute();
214 :
215 : // delete the deleter too
216 : realself->extra.~CustomDeleter<T, Deleter>();
217 : }
218 : static void safetyCheckDeleter(ExternalRefCountData *self)
219 : {
220 : internalSafetyCheckRemove(self);
221 : deleter(self);
222 : }
223 :
224 : static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
225 : {
226 : Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
227 :
228 : // initialize the two sub-objects
229 : new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
230 : new (d) BaseClass(actualDeleter); // can't throw
231 :
232 : return d;
233 : }
234 : private:
235 : // prevent construction
236 : ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
237 : ~ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
238 : Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter)
239 : };
240 :
241 : // This class extends ExternalRefCountData and adds a "T"
242 : // member. That way, when the create() function is called, we allocate
243 : // memory for both QSharedPointer's d-pointer and the actual object being
244 : // tracked.
245 : template <class T>
246 : struct ExternalRefCountWithContiguousData: public ExternalRefCountData
247 : {
248 : typedef ExternalRefCountData Parent;
249 : T data;
250 :
251 : static void deleter(ExternalRefCountData *self)
252 : {
253 : ExternalRefCountWithContiguousData *that =
254 : static_cast<ExternalRefCountWithContiguousData *>(self);
255 : that->data.~T();
256 : Q_UNUSED(that); // MSVC warns if T has a trivial destructor
257 : }
258 : static void safetyCheckDeleter(ExternalRefCountData *self)
259 : {
260 : internalSafetyCheckRemove(self);
261 : deleter(self);
262 : }
263 : static void noDeleter(ExternalRefCountData *) { }
264 :
265 : static inline ExternalRefCountData *create(T **ptr, DestroyerFn destroy)
266 : {
267 : ExternalRefCountWithContiguousData *d =
268 : static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
269 :
270 : // initialize the d-pointer sub-object
271 : // leave d->data uninitialized
272 : new (d) Parent(destroy); // can't throw
273 :
274 : *ptr = &d->data;
275 : return d;
276 : }
277 :
278 : private:
279 : // prevent construction
280 : ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
281 : ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
282 : Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
283 : };
284 :
285 : #ifndef QT_NO_QOBJECT
286 : Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant);
287 : Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant);
288 : #endif
289 : } // namespace QtSharedPointer
290 :
291 : template <class T> class QSharedPointer
292 : {
293 : typedef T *QSharedPointer:: *RestrictedBool;
294 : typedef QtSharedPointer::ExternalRefCountData Data;
295 : public:
296 : typedef T Type;
297 : typedef T element_type;
298 : typedef T value_type;
299 : typedef value_type *pointer;
300 : typedef const value_type *const_pointer;
301 : typedef value_type &reference;
302 : typedef const value_type &const_reference;
303 : typedef qptrdiff difference_type;
304 :
305 : T *data() const Q_DECL_NOTHROW { return value; }
306 : bool isNull() const Q_DECL_NOTHROW { return !data(); }
307 : operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? Q_NULLPTR : &QSharedPointer::value; }
308 : bool operator !() const Q_DECL_NOTHROW { return isNull(); }
309 : T &operator*() const { return *data(); }
310 : T *operator->() const Q_DECL_NOTHROW { return data(); }
311 :
312 : Q_DECL_CONSTEXPR QSharedPointer() Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
313 : ~QSharedPointer() { deref(); }
314 :
315 : Q_DECL_CONSTEXPR QSharedPointer(std::nullptr_t) Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
316 :
317 : template <class X>
318 : inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
319 : { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
320 :
321 : template <class X, typename Deleter>
322 : inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
323 : { internalConstruct(ptr, deleter); }
324 :
325 : template <typename Deleter>
326 : QSharedPointer(std::nullptr_t, Deleter) : value(nullptr), d(nullptr) { }
327 :
328 : QSharedPointer(const QSharedPointer &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
329 : { if (d) ref(); }
330 : QSharedPointer &operator=(const QSharedPointer &other) Q_DECL_NOTHROW
331 : {
332 : QSharedPointer copy(other);
333 : swap(copy);
334 : return *this;
335 : }
336 : #ifdef Q_COMPILER_RVALUE_REFS
337 : QSharedPointer(QSharedPointer &&other) Q_DECL_NOTHROW
338 : : value(other.value), d(other.d)
339 : {
340 : other.d = Q_NULLPTR;
341 : other.value = Q_NULLPTR;
342 : }
343 : QSharedPointer &operator=(QSharedPointer &&other) Q_DECL_NOTHROW
344 : {
345 : QSharedPointer moved(std::move(other));
346 : swap(moved);
347 : return *this;
348 : }
349 :
350 : template <class X>
351 : QSharedPointer(QSharedPointer<X> &&other) Q_DECL_NOTHROW
352 : : value(other.value), d(other.d)
353 : {
354 : other.d = Q_NULLPTR;
355 : other.value = Q_NULLPTR;
356 : }
357 :
358 : template <class X>
359 : QSharedPointer &operator=(QSharedPointer<X> &&other) Q_DECL_NOTHROW
360 : {
361 : QSharedPointer moved(std::move(other));
362 : swap(moved);
363 : return *this;
364 : }
365 :
366 : #endif
367 :
368 : template <class X>
369 : QSharedPointer(const QSharedPointer<X> &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
370 : { if (d) ref(); }
371 :
372 : template <class X>
373 : inline QSharedPointer &operator=(const QSharedPointer<X> &other)
374 : {
375 : QSharedPointer copy(other);
376 : swap(copy);
377 : return *this;
378 : }
379 :
380 : template <class X>
381 : inline QSharedPointer(const QWeakPointer<X> &other) : value(Q_NULLPTR), d(Q_NULLPTR)
382 : { *this = other; }
383 :
384 : template <class X>
385 : inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
386 : { internalSet(other.d, other.value); return *this; }
387 :
388 : inline void swap(QSharedPointer &other)
389 : { this->internalSwap(other); }
390 :
391 : inline void reset() { clear(); }
392 : inline void reset(T *t)
393 : { QSharedPointer copy(t); swap(copy); }
394 : template <typename Deleter>
395 : inline void reset(T *t, Deleter deleter)
396 : { QSharedPointer copy(t, deleter); swap(copy); }
397 :
398 : template <class X>
399 : QSharedPointer<X> staticCast() const
400 : {
401 : return qSharedPointerCast<X, T>(*this);
402 : }
403 :
404 : template <class X>
405 : QSharedPointer<X> dynamicCast() const
406 : {
407 : return qSharedPointerDynamicCast<X, T>(*this);
408 : }
409 :
410 : template <class X>
411 : QSharedPointer<X> constCast() const
412 : {
413 : return qSharedPointerConstCast<X, T>(*this);
414 : }
415 :
416 : #ifndef QT_NO_QOBJECT
417 : template <class X>
418 : QSharedPointer<X> objectCast() const
419 : {
420 : return qSharedPointerObjectCast<X, T>(*this);
421 : }
422 : #endif
423 :
424 : inline void clear() { QSharedPointer copy; swap(copy); }
425 :
426 : QWeakPointer<T> toWeakRef() const;
427 :
428 : template <typename... Args>
429 : static QSharedPointer create(Args && ...arguments)
430 : {
431 : typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
432 : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
433 : typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
434 : # else
435 : typename Private::DestroyerFn destroy = &Private::deleter;
436 : # endif
437 : typename Private::DestroyerFn noDestroy = &Private::noDeleter;
438 : QSharedPointer result(Qt::Uninitialized);
439 : result.d = Private::create(&result.value, noDestroy);
440 :
441 : // now initialize the data
442 : new (result.data()) T(std::forward<Args>(arguments)...);
443 : result.d->destroyer = destroy;
444 : result.d->setQObjectShared(result.value, true);
445 : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
446 : internalSafetyCheckAdd(result.d, result.value);
447 : # endif
448 : result.enableSharedFromThis(result.data());
449 : return result;
450 : }
451 :
452 : private:
453 : explicit QSharedPointer(Qt::Initialization) {}
454 :
455 : void deref() Q_DECL_NOTHROW
456 : { deref(d); }
457 : static void deref(Data *dd) Q_DECL_NOTHROW
458 : {
459 : if (!dd) return;
460 : if (!dd->strongref.deref()) {
461 : dd->destroy();
462 : }
463 : if (!dd->weakref.deref())
464 : delete dd;
465 : }
466 :
467 : template <class X>
468 : inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
469 : {
470 : ptr->initializeFromSharedPointer(constCast<typename std::remove_cv<T>::type>());
471 : }
472 :
473 : inline void enableSharedFromThis(...) {}
474 :
475 : template <typename X, typename Deleter>
476 : inline void internalConstruct(X *ptr, Deleter deleter)
477 : {
478 : if (!ptr) {
479 : d = Q_NULLPTR;
480 : return;
481 : }
482 :
483 : typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
484 : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
485 : typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
486 : # else
487 : typename Private::DestroyerFn actualDeleter = &Private::deleter;
488 : # endif
489 : d = Private::create(ptr, deleter, actualDeleter);
490 :
491 : #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
492 : internalSafetyCheckAdd(d, ptr);
493 : #endif
494 : d->setQObjectShared(ptr, true);
495 : enableSharedFromThis(ptr);
496 : }
497 :
498 : void internalSwap(QSharedPointer &other) Q_DECL_NOTHROW
499 : {
500 : qSwap(d, other.d);
501 : qSwap(this->value, other.value);
502 : }
503 :
504 : #if defined(Q_NO_TEMPLATE_FRIENDS)
505 : public:
506 : #else
507 : template <class X> friend class QSharedPointer;
508 : template <class X> friend class QWeakPointer;
509 : template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
510 : #endif
511 : void ref() const Q_DECL_NOTHROW { d->weakref.ref(); d->strongref.ref(); }
512 :
513 : inline void internalSet(Data *o, T *actual)
514 : {
515 : if (o) {
516 : // increase the strongref, but never up from zero
517 : // or less (-1 is used by QWeakPointer on untracked QObject)
518 : int tmp = o->strongref.load();
519 : while (tmp > 0) {
520 : // try to increment from "tmp" to "tmp + 1"
521 : if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
522 : break; // succeeded
523 : tmp = o->strongref.load(); // failed, try again
524 : }
525 :
526 : if (tmp > 0) {
527 : o->weakref.ref();
528 : } else {
529 : o->checkQObjectShared(actual);
530 : o = Q_NULLPTR;
531 : }
532 : }
533 :
534 : qSwap(d, o);
535 : qSwap(this->value, actual);
536 : if (!d || d->strongref.load() == 0)
537 : this->value = Q_NULLPTR;
538 :
539 : // dereference saved data
540 : deref(o);
541 : }
542 :
543 : Type *value;
544 : Data *d;
545 : };
546 :
547 : template <class T>
548 : class QWeakPointer
549 : {
550 : typedef T *QWeakPointer:: *RestrictedBool;
551 : typedef QtSharedPointer::ExternalRefCountData Data;
552 :
553 : public:
554 : typedef T element_type;
555 : typedef T value_type;
556 : typedef value_type *pointer;
557 : typedef const value_type *const_pointer;
558 : typedef value_type &reference;
559 : typedef const value_type &const_reference;
560 : typedef qptrdiff difference_type;
561 :
562 : bool isNull() const Q_DECL_NOTHROW { return d == Q_NULLPTR || d->strongref.load() == 0 || value == Q_NULLPTR; }
563 : operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? Q_NULLPTR : &QWeakPointer::value; }
564 : bool operator !() const Q_DECL_NOTHROW { return isNull(); }
565 0 : T *data() const Q_DECL_NOTHROW { return d == Q_NULLPTR || d->strongref.load() == 0 ? Q_NULLPTR : value; }
566 :
567 0 : inline QWeakPointer() Q_DECL_NOTHROW : d(Q_NULLPTR), value(Q_NULLPTR) { }
568 0 : inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
569 :
570 : #ifndef QT_NO_QOBJECT
571 : // special constructor that is enabled only if X derives from QObject
572 : #if QT_DEPRECATED_SINCE(5, 0)
573 : template <class X>
574 : QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : Q_NULLPTR), value(ptr)
575 : { }
576 : #endif
577 : #endif
578 :
579 : #if QT_DEPRECATED_SINCE(5, 0)
580 : template <class X>
581 : QT_DEPRECATED inline QWeakPointer &operator=(X *ptr)
582 : { return *this = QWeakPointer(ptr); }
583 : #endif
584 :
585 : QWeakPointer(const QWeakPointer &other) Q_DECL_NOTHROW : d(other.d), value(other.value)
586 : { if (d) d->weakref.ref(); }
587 : #ifdef Q_COMPILER_RVALUE_REFS
588 0 : QWeakPointer(QWeakPointer &&other) Q_DECL_NOTHROW
589 0 : : d(other.d), value(other.value)
590 : {
591 0 : other.d = Q_NULLPTR;
592 0 : other.value = Q_NULLPTR;
593 0 : }
594 0 : QWeakPointer &operator=(QWeakPointer &&other) Q_DECL_NOTHROW
595 0 : { QWeakPointer moved(std::move(other)); swap(moved); return *this; }
596 : #endif
597 : QWeakPointer &operator=(const QWeakPointer &other) Q_DECL_NOTHROW
598 : {
599 : QWeakPointer copy(other);
600 : swap(copy);
601 : return *this;
602 : }
603 :
604 0 : void swap(QWeakPointer &other) Q_DECL_NOTHROW
605 : {
606 0 : qSwap(this->d, other.d);
607 0 : qSwap(this->value, other.value);
608 0 : }
609 :
610 : inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
611 : { if (d) d->weakref.ref();}
612 : inline QWeakPointer &operator=(const QSharedPointer<T> &o)
613 : {
614 : internalSet(o.d, o.value);
615 : return *this;
616 : }
617 :
618 : template <class X>
619 : inline QWeakPointer(const QWeakPointer<X> &o) : d(Q_NULLPTR), value(Q_NULLPTR)
620 : { *this = o; }
621 :
622 : template <class X>
623 : inline QWeakPointer &operator=(const QWeakPointer<X> &o)
624 : {
625 : // conversion between X and T could require access to the virtual table
626 : // so force the operation to go through QSharedPointer
627 : *this = o.toStrongRef();
628 : return *this;
629 : }
630 :
631 : template <class X>
632 : bool operator==(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
633 : { return d == o.d && value == static_cast<const T *>(o.value); }
634 :
635 : template <class X>
636 : bool operator!=(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
637 : { return !(*this == o); }
638 :
639 : template <class X>
640 : inline QWeakPointer(const QSharedPointer<X> &o) : d(Q_NULLPTR), value(Q_NULLPTR)
641 : { *this = o; }
642 :
643 : template <class X>
644 : inline QWeakPointer &operator=(const QSharedPointer<X> &o)
645 : {
646 : QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
647 : internalSet(o.d, o.data());
648 : return *this;
649 : }
650 :
651 : template <class X>
652 : bool operator==(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
653 : { return d == o.d; }
654 :
655 : template <class X>
656 : bool operator!=(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
657 : { return !(*this == o); }
658 :
659 : inline void clear() { *this = QWeakPointer(); }
660 :
661 : inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
662 : // std::weak_ptr compatibility:
663 : inline QSharedPointer<T> lock() const { return toStrongRef(); }
664 :
665 : #if defined(QWEAKPOINTER_ENABLE_ARROW)
666 : inline T *operator->() const { return data(); }
667 : #endif
668 :
669 : private:
670 :
671 : #if defined(Q_NO_TEMPLATE_FRIENDS)
672 : public:
673 : #else
674 : template <class X> friend class QSharedPointer;
675 : template <class X> friend class QPointer;
676 : #endif
677 :
678 : template <class X>
679 0 : inline QWeakPointer &assign(X *ptr)
680 0 : { return *this = QWeakPointer<X>(ptr, true); }
681 :
682 : #ifndef QT_NO_QOBJECT
683 : template <class X>
684 0 : inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : Q_NULLPTR), value(ptr)
685 0 : { }
686 : #endif
687 :
688 : inline void internalSet(Data *o, T *actual)
689 : {
690 : if (d == o) return;
691 : if (o)
692 : o->weakref.ref();
693 : if (d && !d->weakref.deref())
694 : delete d;
695 : d = o;
696 : value = actual;
697 : }
698 :
699 : Data *d;
700 : T *value;
701 : };
702 :
703 : template <class T>
704 : class QEnableSharedFromThis
705 : {
706 : protected:
707 : #ifdef Q_COMPILER_DEFAULT_MEMBERS
708 : QEnableSharedFromThis() = default;
709 : #else
710 : Q_DECL_CONSTEXPR QEnableSharedFromThis() {}
711 : #endif
712 : QEnableSharedFromThis(const QEnableSharedFromThis &) {}
713 : QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
714 :
715 : public:
716 : inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
717 : inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
718 :
719 : #ifndef Q_NO_TEMPLATE_FRIENDS
720 : private:
721 : template <class X> friend class QSharedPointer;
722 : #else
723 : public:
724 : #endif
725 : template <class X>
726 : inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
727 : {
728 : weakPointer = ptr;
729 : }
730 :
731 : mutable QWeakPointer<T> weakPointer;
732 : };
733 :
734 : //
735 : // operator== and operator!=
736 : //
737 : template <class T, class X>
738 : bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
739 : {
740 : return ptr1.data() == ptr2.data();
741 : }
742 : template <class T, class X>
743 : bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
744 : {
745 : return ptr1.data() != ptr2.data();
746 : }
747 :
748 : template <class T, class X>
749 : bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
750 : {
751 : return ptr1.data() == ptr2;
752 : }
753 : template <class T, class X>
754 : bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
755 : {
756 : return ptr1 == ptr2.data();
757 : }
758 : template <class T, class X>
759 : bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
760 : {
761 : return !(ptr1 == ptr2);
762 : }
763 : template <class T, class X>
764 : bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
765 : {
766 : return !(ptr2 == ptr1);
767 : }
768 :
769 : template <class T, class X>
770 : bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
771 : {
772 : return ptr2 == ptr1;
773 : }
774 : template <class T, class X>
775 : bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
776 : {
777 : return ptr2 != ptr1;
778 : }
779 :
780 : template<class T>
781 : inline bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
782 : {
783 : return lhs.isNull();
784 : }
785 :
786 : template<class T>
787 : inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
788 : {
789 : return !lhs.isNull();
790 : }
791 :
792 : template<class T>
793 : inline bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
794 : {
795 : return rhs.isNull();
796 : }
797 :
798 : template<class T>
799 : inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
800 : {
801 : return !rhs.isNull();
802 : }
803 :
804 : template<class T>
805 : inline bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
806 : {
807 : return lhs.isNull();
808 : }
809 :
810 : template<class T>
811 : inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
812 : {
813 : return !lhs.isNull();
814 : }
815 :
816 : template<class T>
817 : inline bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
818 : {
819 : return rhs.isNull();
820 : }
821 :
822 : template<class T>
823 : inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
824 : {
825 : return !rhs.isNull();
826 : }
827 :
828 : //
829 : // operator-
830 : //
831 : template <class T, class X>
832 : Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
833 : {
834 : return ptr1.data() - ptr2.data();
835 : }
836 : template <class T, class X>
837 : Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
838 : {
839 : return ptr1.data() - ptr2;
840 : }
841 : template <class T, class X>
842 : Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
843 : {
844 : return ptr1 - ptr2.data();
845 : }
846 :
847 : //
848 : // operator<
849 : //
850 : template <class T, class X>
851 : Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
852 : {
853 : using CT = typename std::common_type<T *, X *>::type;
854 : return std::less<CT>()(ptr1.data(), ptr2.data());
855 : }
856 : template <class T, class X>
857 : Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
858 : {
859 : using CT = typename std::common_type<T *, X *>::type;
860 : return std::less<CT>()(ptr1.data(), ptr2);
861 : }
862 : template <class T, class X>
863 : Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
864 : {
865 : using CT = typename std::common_type<T *, X *>::type;
866 : return std::less<CT>()(ptr1, ptr2.data());
867 : }
868 :
869 : //
870 : // qHash
871 : //
872 : template <class T>
873 : Q_INLINE_TEMPLATE uint qHash(const QSharedPointer<T> &ptr, uint seed = 0)
874 : {
875 : return QT_PREPEND_NAMESPACE(qHash)(ptr.data(), seed);
876 : }
877 :
878 :
879 : template <class T>
880 : Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
881 : {
882 : return QWeakPointer<T>(*this);
883 : }
884 :
885 : template <class T>
886 : inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
887 : {
888 : p1.swap(p2);
889 : }
890 :
891 : QT_END_NAMESPACE
892 : namespace std {
893 : template <class T>
894 : inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2)
895 : { p1.swap(p2); }
896 : }
897 : QT_BEGIN_NAMESPACE
898 :
899 : namespace QtSharedPointer {
900 : // helper functions:
901 : template <class X, class T>
902 : Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
903 : {
904 : QSharedPointer<X> result;
905 : result.internalSet(src.d, ptr);
906 : return result;
907 : }
908 : }
909 :
910 : // cast operators
911 : template <class X, class T>
912 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
913 : {
914 : X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
915 : return QtSharedPointer::copyAndSetPointer(ptr, src);
916 : }
917 : template <class X, class T>
918 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
919 : {
920 : return qSharedPointerCast<X, T>(src.toStrongRef());
921 : }
922 :
923 : template <class X, class T>
924 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
925 : {
926 : X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
927 : if (!ptr)
928 : return QSharedPointer<X>();
929 : return QtSharedPointer::copyAndSetPointer(ptr, src);
930 : }
931 : template <class X, class T>
932 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
933 : {
934 : return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
935 : }
936 :
937 : template <class X, class T>
938 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
939 : {
940 : X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
941 : return QtSharedPointer::copyAndSetPointer(ptr, src);
942 : }
943 : template <class X, class T>
944 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
945 : {
946 : return qSharedPointerConstCast<X, T>(src.toStrongRef());
947 : }
948 :
949 : template <class X, class T>
950 : Q_INLINE_TEMPLATE
951 : QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
952 : {
953 : return qSharedPointerCast<X, T>(src).toWeakRef();
954 : }
955 :
956 : #ifndef QT_NO_QOBJECT
957 : template <class X, class T>
958 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
959 : {
960 : X *ptr = qobject_cast<X *>(src.data());
961 : return QtSharedPointer::copyAndSetPointer(ptr, src);
962 : }
963 : template <class X, class T>
964 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
965 : {
966 : return qSharedPointerObjectCast<X>(src.toStrongRef());
967 : }
968 :
969 : template <class X, class T>
970 : inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
971 : qobject_cast(const QSharedPointer<T> &src)
972 : {
973 : return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
974 : }
975 : template <class X, class T>
976 : inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
977 : qobject_cast(const QWeakPointer<T> &src)
978 : {
979 : return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
980 : }
981 :
982 : template<typename T>
983 : QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
984 : qWeakPointerFromVariant(const QVariant &variant)
985 : {
986 : return QWeakPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
987 : }
988 : template<typename T>
989 : QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
990 : qSharedPointerFromVariant(const QVariant &variant)
991 : {
992 : return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
993 : }
994 :
995 : #endif
996 :
997 : template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
998 : template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE);
999 :
1000 :
1001 : QT_END_NAMESPACE
1002 :
1003 : #endif
|