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