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

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