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

source code of qtbase/src/corelib/tools/qsharedpointer_impl.h