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
57QT_BEGIN_NAMESPACE
58QT_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
70QT_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
82template<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//
90template <class T> class QWeakPointer;
91template <class T> class QSharedPointer;
92template <class T> class QEnableSharedFromThis;
93
94class QVariant;
95
96template <class X, class T>
97QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
98template <class X, class T>
99QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
100template <class X, class T>
101QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
102
103#ifndef QT_NO_QOBJECT
104template <class X, class T>
105QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
106#endif
107
108namespace 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 ~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 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 typedef typename std::remove_cv<T>::type NoCVType;
250 NoCVType data;
251
252 static void deleter(ExternalRefCountData *self)
253 {
254 ExternalRefCountWithContiguousData *that =
255 static_cast<ExternalRefCountWithContiguousData *>(self);
256 that->data.~T();
257 Q_UNUSED(that); // MSVC warns if T has a trivial destructor
258 }
259 static void safetyCheckDeleter(ExternalRefCountData *self)
260 {
261 internalSafetyCheckRemove(self);
262 deleter(self);
263 }
264 static void noDeleter(ExternalRefCountData *) { }
265
266 static inline ExternalRefCountData *create(NoCVType **ptr, DestroyerFn destroy)
267 {
268 ExternalRefCountWithContiguousData *d =
269 static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
270
271 // initialize the d-pointer sub-object
272 // leave d->data uninitialized
273 new (d) Parent(destroy); // can't throw
274
275 *ptr = &d->data;
276 return d;
277 }
278
279 private:
280 // prevent construction
281 ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
282 ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
283 Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
284 };
285
286#ifndef QT_NO_QOBJECT
287 Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant);
288 Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant);
289#endif
290} // namespace QtSharedPointer
291
292template <class T> class QSharedPointer
293{
294 typedef T *QSharedPointer:: *RestrictedBool;
295 typedef QtSharedPointer::ExternalRefCountData Data;
296public:
297 typedef T Type;
298 typedef T element_type;
299 typedef T value_type;
300 typedef value_type *pointer;
301 typedef const value_type *const_pointer;
302 typedef value_type &reference;
303 typedef const value_type &const_reference;
304 typedef qptrdiff difference_type;
305
306 T *data() const Q_DECL_NOTHROW { return value; }
307 T *get() const Q_DECL_NOTHROW { return value; }
308 bool isNull() const Q_DECL_NOTHROW { return !data(); }
309 operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? nullptr : &QSharedPointer::value; }
310 bool operator !() const Q_DECL_NOTHROW { return isNull(); }
311 T &operator*() const { return *data(); }
312 T *operator->() const Q_DECL_NOTHROW { return data(); }
313
314 Q_DECL_CONSTEXPR QSharedPointer() Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
315 ~QSharedPointer() { deref(); }
316
317 Q_DECL_CONSTEXPR QSharedPointer(std::nullptr_t) Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
318
319 template <class X>
320 inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
321 { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
322
323 template <class X, typename Deleter>
324 inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
325 { internalConstruct(ptr, deleter); }
326
327 template <typename Deleter>
328 QSharedPointer(std::nullptr_t, Deleter) : value(nullptr), d(nullptr) { }
329
330 QSharedPointer(const QSharedPointer &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
331 { if (d) ref(); }
332 QSharedPointer &operator=(const QSharedPointer &other) Q_DECL_NOTHROW
333 {
334 QSharedPointer copy(other);
335 swap(copy);
336 return *this;
337 }
338#ifdef Q_COMPILER_RVALUE_REFS
339 QSharedPointer(QSharedPointer &&other) Q_DECL_NOTHROW
340 : value(other.value), d(other.d)
341 {
342 other.d = nullptr;
343 other.value = nullptr;
344 }
345 QSharedPointer &operator=(QSharedPointer &&other) Q_DECL_NOTHROW
346 {
347 QSharedPointer moved(std::move(other));
348 swap(moved);
349 return *this;
350 }
351
352 template <class X>
353 QSharedPointer(QSharedPointer<X> &&other) Q_DECL_NOTHROW
354 : value(other.value), d(other.d)
355 {
356 other.d = nullptr;
357 other.value = nullptr;
358 }
359
360 template <class X>
361 QSharedPointer &operator=(QSharedPointer<X> &&other) Q_DECL_NOTHROW
362 {
363 QSharedPointer moved(std::move(other));
364 swap(moved);
365 return *this;
366 }
367
368#endif
369
370 template <class X>
371 QSharedPointer(const QSharedPointer<X> &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
372 { if (d) ref(); }
373
374 template <class X>
375 inline QSharedPointer &operator=(const QSharedPointer<X> &other)
376 {
377 QSharedPointer copy(other);
378 swap(copy);
379 return *this;
380 }
381
382 template <class X>
383 inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
384 { *this = other; }
385
386 template <class X>
387 inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
388 { internalSet(other.d, other.value); return *this; }
389
390 inline void swap(QSharedPointer &other)
391 { this->internalSwap(other); }
392
393 inline void reset() { clear(); }
394 inline void reset(T *t)
395 { QSharedPointer copy(t); swap(copy); }
396 template <typename Deleter>
397 inline void reset(T *t, Deleter deleter)
398 { QSharedPointer copy(t, deleter); swap(copy); }
399
400 template <class X>
401 QSharedPointer<X> staticCast() const
402 {
403 return qSharedPointerCast<X, T>(*this);
404 }
405
406 template <class X>
407 QSharedPointer<X> dynamicCast() const
408 {
409 return qSharedPointerDynamicCast<X, T>(*this);
410 }
411
412 template <class X>
413 QSharedPointer<X> constCast() const
414 {
415 return qSharedPointerConstCast<X, T>(*this);
416 }
417
418#ifndef QT_NO_QOBJECT
419 template <class X>
420 QSharedPointer<X> objectCast() const
421 {
422 return qSharedPointerObjectCast<X, T>(*this);
423 }
424#endif
425
426 inline void clear() { QSharedPointer copy; swap(copy); }
427
428 QWeakPointer<T> toWeakRef() const;
429
430 template <typename... Args>
431 static QSharedPointer create(Args && ...arguments)
432 {
433 typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
434# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
435 typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
436# else
437 typename Private::DestroyerFn destroy = &Private::deleter;
438# endif
439 typename Private::DestroyerFn noDestroy = &Private::noDeleter;
440 QSharedPointer result(Qt::Uninitialized);
441 typename std::remove_cv<T>::type *ptr;
442 result.d = Private::create(&ptr, noDestroy);
443
444 // now initialize the data
445 new (ptr) T(std::forward<Args>(arguments)...);
446 result.value = ptr;
447 result.d->destroyer = destroy;
448 result.d->setQObjectShared(result.value, true);
449# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
450 internalSafetyCheckAdd(result.d, result.value);
451# endif
452 result.enableSharedFromThis(result.data());
453 return result;
454 }
455
456private:
457 explicit QSharedPointer(Qt::Initialization) {}
458
459 void deref() Q_DECL_NOTHROW
460 { deref(d); }
461 static void deref(Data *dd) Q_DECL_NOTHROW
462 {
463 if (!dd) return;
464 if (!dd->strongref.deref()) {
465 dd->destroy();
466 }
467 if (!dd->weakref.deref())
468 delete dd;
469 }
470
471 template <class X>
472 inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
473 {
474 ptr->initializeFromSharedPointer(constCast<typename std::remove_cv<T>::type>());
475 }
476
477 inline void enableSharedFromThis(...) {}
478
479 template <typename X, typename Deleter>
480 inline void internalConstruct(X *ptr, Deleter deleter)
481 {
482 if (!ptr) {
483 d = nullptr;
484 return;
485 }
486
487 typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
488# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
489 typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
490# else
491 typename Private::DestroyerFn actualDeleter = &Private::deleter;
492# endif
493 d = Private::create(ptr, deleter, actualDeleter);
494
495#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
496 internalSafetyCheckAdd(d, ptr);
497#endif
498 d->setQObjectShared(ptr, true);
499 enableSharedFromThis(ptr);
500 }
501
502 void internalSwap(QSharedPointer &other) Q_DECL_NOTHROW
503 {
504 qSwap(d, other.d);
505 qSwap(this->value, other.value);
506 }
507
508#if defined(Q_NO_TEMPLATE_FRIENDS)
509public:
510#else
511 template <class X> friend class QSharedPointer;
512 template <class X> friend class QWeakPointer;
513 template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
514#endif
515 void ref() const Q_DECL_NOTHROW { d->weakref.ref(); d->strongref.ref(); }
516
517 inline void internalSet(Data *o, T *actual)
518 {
519 if (o) {
520 // increase the strongref, but never up from zero
521 // or less (-1 is used by QWeakPointer on untracked QObject)
522 int tmp = o->strongref.load();
523 while (tmp > 0) {
524 // try to increment from "tmp" to "tmp + 1"
525 if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
526 break; // succeeded
527 tmp = o->strongref.load(); // failed, try again
528 }
529
530 if (tmp > 0) {
531 o->weakref.ref();
532 } else {
533 o->checkQObjectShared(actual);
534 o = nullptr;
535 }
536 }
537
538 qSwap(d, o);
539 qSwap(this->value, actual);
540 if (!d || d->strongref.load() == 0)
541 this->value = nullptr;
542
543 // dereference saved data
544 deref(o);
545 }
546
547 Type *value;
548 Data *d;
549};
550
551template <class T>
552class QWeakPointer
553{
554 typedef T *QWeakPointer:: *RestrictedBool;
555 typedef QtSharedPointer::ExternalRefCountData Data;
556
557public:
558 typedef T element_type;
559 typedef T value_type;
560 typedef value_type *pointer;
561 typedef const value_type *const_pointer;
562 typedef value_type &reference;
563 typedef const value_type &const_reference;
564 typedef qptrdiff difference_type;
565
566 bool isNull() const Q_DECL_NOTHROW { return d == nullptr || d->strongref.load() == 0 || value == nullptr; }
567 operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? nullptr : &QWeakPointer::value; }
568 bool operator !() const Q_DECL_NOTHROW { return isNull(); }
569 T *data() const Q_DECL_NOTHROW { return d == nullptr || d->strongref.load() == 0 ? nullptr : value; }
570
571 inline QWeakPointer() Q_DECL_NOTHROW : d(nullptr), value(nullptr) { }
572 inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
573
574#ifndef QT_NO_QOBJECT
575 // special constructor that is enabled only if X derives from QObject
576#if QT_DEPRECATED_SINCE(5, 0)
577 template <class X>
578 QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
579 { }
580#endif
581#endif
582
583#if QT_DEPRECATED_SINCE(5, 0)
584 template <class X>
585 QT_DEPRECATED inline QWeakPointer &operator=(X *ptr)
586 { return *this = QWeakPointer(ptr); }
587#endif
588
589 QWeakPointer(const QWeakPointer &other) Q_DECL_NOTHROW : d(other.d), value(other.value)
590 { if (d) d->weakref.ref(); }
591#ifdef Q_COMPILER_RVALUE_REFS
592 QWeakPointer(QWeakPointer &&other) Q_DECL_NOTHROW
593 : d(other.d), value(other.value)
594 {
595 other.d = nullptr;
596 other.value = nullptr;
597 }
598 QWeakPointer &operator=(QWeakPointer &&other) Q_DECL_NOTHROW
599 { QWeakPointer moved(std::move(other)); swap(moved); return *this; }
600#endif
601 QWeakPointer &operator=(const QWeakPointer &other) Q_DECL_NOTHROW
602 {
603 QWeakPointer copy(other);
604 swap(copy);
605 return *this;
606 }
607
608 void swap(QWeakPointer &other) Q_DECL_NOTHROW
609 {
610 qSwap(this->d, other.d);
611 qSwap(this->value, other.value);
612 }
613
614 inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
615 { if (d) d->weakref.ref();}
616 inline QWeakPointer &operator=(const QSharedPointer<T> &o)
617 {
618 internalSet(o.d, o.value);
619 return *this;
620 }
621
622 template <class X>
623 inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
624 { *this = o; }
625
626 template <class X>
627 inline QWeakPointer &operator=(const QWeakPointer<X> &o)
628 {
629 // conversion between X and T could require access to the virtual table
630 // so force the operation to go through QSharedPointer
631 *this = o.toStrongRef();
632 return *this;
633 }
634
635 template <class X>
636 bool operator==(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
637 { return d == o.d && value == static_cast<const T *>(o.value); }
638
639 template <class X>
640 bool operator!=(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
641 { return !(*this == o); }
642
643 template <class X>
644 inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
645 { *this = o; }
646
647 template <class X>
648 inline QWeakPointer &operator=(const QSharedPointer<X> &o)
649 {
650 QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
651 internalSet(o.d, o.data());
652 return *this;
653 }
654
655 template <class X>
656 bool operator==(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
657 { return d == o.d; }
658
659 template <class X>
660 bool operator!=(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
661 { return !(*this == o); }
662
663 inline void clear() { *this = QWeakPointer(); }
664
665 inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
666 // std::weak_ptr compatibility:
667 inline QSharedPointer<T> lock() const { return toStrongRef(); }
668
669#if defined(QWEAKPOINTER_ENABLE_ARROW)
670 inline T *operator->() const { return data(); }
671#endif
672
673private:
674
675#if defined(Q_NO_TEMPLATE_FRIENDS)
676public:
677#else
678 template <class X> friend class QSharedPointer;
679 template <class X> friend class QPointer;
680#endif
681
682 template <class X>
683 inline QWeakPointer &assign(X *ptr)
684 { return *this = QWeakPointer<X>(ptr, true); }
685
686#ifndef QT_NO_QOBJECT
687 template <class X>
688 inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
689 { }
690#endif
691
692 inline void internalSet(Data *o, T *actual)
693 {
694 if (d == o) return;
695 if (o)
696 o->weakref.ref();
697 if (d && !d->weakref.deref())
698 delete d;
699 d = o;
700 value = actual;
701 }
702
703 Data *d;
704 T *value;
705};
706
707template <class T>
708class QEnableSharedFromThis
709{
710protected:
711#ifdef Q_COMPILER_DEFAULT_MEMBERS
712 QEnableSharedFromThis() = default;
713#else
714 Q_DECL_CONSTEXPR QEnableSharedFromThis() {}
715#endif
716 QEnableSharedFromThis(const QEnableSharedFromThis &) {}
717 QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
718
719public:
720 inline QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); }
721 inline QSharedPointer<const T> sharedFromThis() const { return QSharedPointer<const T>(weakPointer); }
722
723#ifndef Q_NO_TEMPLATE_FRIENDS
724private:
725 template <class X> friend class QSharedPointer;
726#else
727public:
728#endif
729 template <class X>
730 inline void initializeFromSharedPointer(const QSharedPointer<X> &ptr) const
731 {
732 weakPointer = ptr;
733 }
734
735 mutable QWeakPointer<T> weakPointer;
736};
737
738//
739// operator== and operator!=
740//
741template <class T, class X>
742bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
743{
744 return ptr1.data() == ptr2.data();
745}
746template <class T, class X>
747bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
748{
749 return ptr1.data() != ptr2.data();
750}
751
752template <class T, class X>
753bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
754{
755 return ptr1.data() == ptr2;
756}
757template <class T, class X>
758bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
759{
760 return ptr1 == ptr2.data();
761}
762template <class T, class X>
763bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
764{
765 return !(ptr1 == ptr2);
766}
767template <class T, class X>
768bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
769{
770 return !(ptr2 == ptr1);
771}
772
773template <class T, class X>
774bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
775{
776 return ptr2 == ptr1;
777}
778template <class T, class X>
779bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
780{
781 return ptr2 != ptr1;
782}
783
784template<class T>
785inline bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
786{
787 return lhs.isNull();
788}
789
790template<class T>
791inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
792{
793 return !lhs.isNull();
794}
795
796template<class T>
797inline bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
798{
799 return rhs.isNull();
800}
801
802template<class T>
803inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
804{
805 return !rhs.isNull();
806}
807
808template<class T>
809inline bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
810{
811 return lhs.isNull();
812}
813
814template<class T>
815inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
816{
817 return !lhs.isNull();
818}
819
820template<class T>
821inline bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
822{
823 return rhs.isNull();
824}
825
826template<class T>
827inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
828{
829 return !rhs.isNull();
830}
831
832//
833// operator-
834//
835template <class T, class X>
836Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
837{
838 return ptr1.data() - ptr2.data();
839}
840template <class T, class X>
841Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
842{
843 return ptr1.data() - ptr2;
844}
845template <class T, class X>
846Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
847{
848 return ptr1 - ptr2.data();
849}
850
851//
852// operator<
853//
854template <class T, class X>
855Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
856{
857 using CT = typename std::common_type<T *, X *>::type;
858 return std::less<CT>()(ptr1.data(), ptr2.data());
859}
860template <class T, class X>
861Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
862{
863 using CT = typename std::common_type<T *, X *>::type;
864 return std::less<CT>()(ptr1.data(), ptr2);
865}
866template <class T, class X>
867Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
868{
869 using CT = typename std::common_type<T *, X *>::type;
870 return std::less<CT>()(ptr1, ptr2.data());
871}
872
873//
874// qHash
875//
876template <class T>
877Q_INLINE_TEMPLATE uint qHash(const QSharedPointer<T> &ptr, uint seed = 0)
878{
879 return QT_PREPEND_NAMESPACE(qHash)(ptr.data(), seed);
880}
881
882
883template <class T>
884Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
885{
886 return QWeakPointer<T>(*this);
887}
888
889template <class T>
890inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
891{
892 p1.swap(p2);
893}
894
895QT_END_NAMESPACE
896namespace std {
897 template <class T>
898 inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2)
899 { p1.swap(p2); }
900}
901QT_BEGIN_NAMESPACE
902
903namespace QtSharedPointer {
904// helper functions:
905 template <class X, class T>
906 Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
907 {
908 QSharedPointer<X> result;
909 result.internalSet(src.d, ptr);
910 return result;
911 }
912}
913
914// cast operators
915template <class X, class T>
916Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
917{
918 X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
919 return QtSharedPointer::copyAndSetPointer(ptr, src);
920}
921template <class X, class T>
922Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
923{
924 return qSharedPointerCast<X, T>(src.toStrongRef());
925}
926
927template <class X, class T>
928Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
929{
930 X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
931 if (!ptr)
932 return QSharedPointer<X>();
933 return QtSharedPointer::copyAndSetPointer(ptr, src);
934}
935template <class X, class T>
936Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
937{
938 return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
939}
940
941template <class X, class T>
942Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
943{
944 X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
945 return QtSharedPointer::copyAndSetPointer(ptr, src);
946}
947template <class X, class T>
948Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
949{
950 return qSharedPointerConstCast<X, T>(src.toStrongRef());
951}
952
953template <class X, class T>
954Q_INLINE_TEMPLATE
955QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
956{
957 return qSharedPointerCast<X, T>(src).toWeakRef();
958}
959
960#ifndef QT_NO_QOBJECT
961template <class X, class T>
962Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
963{
964 X *ptr = qobject_cast<X *>(src.data());
965 return QtSharedPointer::copyAndSetPointer(ptr, src);
966}
967template <class X, class T>
968Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
969{
970 return qSharedPointerObjectCast<X>(src.toStrongRef());
971}
972
973template <class X, class T>
974inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
975qobject_cast(const QSharedPointer<T> &src)
976{
977 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
978}
979template <class X, class T>
980inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
981qobject_cast(const QWeakPointer<T> &src)
982{
983 return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
984}
985
986template<typename T>
987QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
988qWeakPointerFromVariant(const QVariant &variant)
989{
990 return QWeakPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
991}
992template<typename T>
993QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
994qSharedPointerFromVariant(const QVariant &variant)
995{
996 return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
997}
998
999#endif
1000
1001template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
1002template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE);
1003
1004
1005QT_END_NAMESPACE
1006
1007#endif
1008