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