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

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