Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 : ** Contact: http://www.qt-project.org/legal
5 : **
6 : ** This file is part of the QtCore module of the Qt Toolkit.
7 : **
8 : ** $QT_BEGIN_LICENSE:LGPL$
9 : ** Commercial License Usage
10 : ** Licensees holding valid commercial Qt licenses may use this file in
11 : ** accordance with the commercial license agreement provided with the
12 : ** Software or, alternatively, in accordance with the terms contained in
13 : ** a written agreement between you and Digia. For licensing terms and
14 : ** conditions see http://qt.digia.com/licensing. For further information
15 : ** use the contact form at http://qt.digia.com/contact-us.
16 : **
17 : ** GNU Lesser General Public License Usage
18 : ** Alternatively, this file may be used under the terms of the GNU Lesser
19 : ** General Public License version 2.1 as published by the Free Software
20 : ** Foundation and appearing in the file LICENSE.LGPL included in the
21 : ** packaging of this file. Please review the following information to
22 : ** ensure the GNU Lesser General Public License version 2.1 requirements
23 : ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 : **
25 : ** In addition, as a special exception, Digia gives you certain additional
26 : ** rights. These rights are described in the Digia Qt LGPL Exception
27 : ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 : **
29 : ** GNU General Public License Usage
30 : ** Alternatively, this file may be used under the terms of the GNU
31 : ** General Public License version 3.0 as published by the Free Software
32 : ** Foundation and appearing in the file LICENSE.GPL included in the
33 : ** packaging of this file. Please review the following information to
34 : ** ensure the GNU General Public License version 3.0 requirements will be
35 : ** met: http://www.gnu.org/copyleft/gpl.html.
36 : **
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
58 : QT_BEGIN_NAMESPACE
59 : QT_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/qhash.h> // for qHash
67 :
68 : #if defined(Q_COMPILER_RVALUE_REFS) && defined(Q_COMPILER_VARIADIC_TEMPLATES)
69 : # include <utility> // for std::forward
70 : #endif
71 :
72 : QT_BEGIN_NAMESPACE
73 :
74 :
75 : // Macro QSHAREDPOINTER_VERIFY_AUTO_CAST
76 : // generates a compiler error if the following construct isn't valid:
77 : // T *ptr1;
78 : // X *ptr2 = ptr1;
79 : //
80 : #ifdef QT_NO_DEBUG
81 : # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) qt_noop()
82 : #else
83 :
84 : template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
85 : # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) \
86 : qt_sharedpointer_cast_check<T>(static_cast<X *>(0))
87 : #endif
88 :
89 : //
90 : // forward declarations
91 : //
92 : template <class T> class QWeakPointer;
93 : template <class T> class QSharedPointer;
94 :
95 : class QVariant;
96 :
97 : template <class X, class T>
98 : QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr);
99 : template <class X, class T>
100 : QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr);
101 : template <class X, class T>
102 : QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr);
103 :
104 : #ifndef QT_NO_QOBJECT
105 : template <class X, class T>
106 : QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
107 : #endif
108 :
109 : namespace QtSharedPointer {
110 : template <class T> class ExternalRefCount;
111 :
112 : template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
113 :
114 : // used in debug mode to verify the reuse of pointers
115 : Q_CORE_EXPORT void internalSafetyCheckAdd(const void *, const volatile void *);
116 : Q_CORE_EXPORT void internalSafetyCheckRemove(const void *);
117 :
118 : template <class T, typename Klass, typename RetVal>
119 : inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)())
120 : { (t->*memberDeleter)(); }
121 : template <class T, typename Deleter>
122 : inline void executeDeleter(T *t, Deleter d)
123 : { d(t); }
124 : struct NormalDeleter {};
125 :
126 : // this uses partial template specialization
127 : template <class T> struct RemovePointer;
128 : template <class T> struct RemovePointer<T *> { typedef T Type; };
129 : template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
130 : template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
131 :
132 : // This class is the d-pointer of QSharedPointer and QWeakPointer.
133 : //
134 : // It is a reference-counted reference counter. "strongref" is the inner
135 : // reference counter, and it tracks the lifetime of the pointer itself.
136 : // "weakref" is the outer reference counter and it tracks the lifetime of
137 : // the ExternalRefCountData object.
138 : //
139 : // The deleter is stored in the destroyer member and is always a pointer to
140 : // a static function in ExternalRefCountWithCustomDeleter or in
141 : // ExternalRefCountWithContiguousData
142 : struct ExternalRefCountData
143 : {
144 : typedef void (*DestroyerFn)(ExternalRefCountData *);
145 : QBasicAtomicInt weakref;
146 : QBasicAtomicInt strongref;
147 : DestroyerFn destroyer;
148 :
149 : inline ExternalRefCountData(DestroyerFn d)
150 : : destroyer(d)
151 : {
152 : strongref.store(1);
153 : weakref.store(1);
154 : }
155 : inline ExternalRefCountData(Qt::Initialization) { }
156 0 : ~ExternalRefCountData() { Q_ASSERT(!weakref.load()); Q_ASSERT(strongref.load() <= 0); }
157 :
158 : void destroy() { destroyer(this); }
159 :
160 : #ifndef QT_NO_QOBJECT
161 : Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
162 : Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
163 : Q_CORE_EXPORT void checkQObjectShared(const QObject *);
164 : #endif
165 : inline void checkQObjectShared(...) { }
166 : inline void setQObjectShared(...) { }
167 :
168 0 : inline void operator delete(void *ptr) { ::operator delete(ptr); }
169 : inline void operator delete(void *, void *) { }
170 : };
171 : // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit)
172 :
173 : template <class T, typename Deleter>
174 : struct CustomDeleter
175 : {
176 : Deleter deleter;
177 : T *ptr;
178 :
179 : CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
180 : void execute() { executeDeleter(ptr, deleter); }
181 : };
182 : // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding
183 : // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding
184 : // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
185 : // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
186 :
187 : // This specialization of CustomDeleter for a deleter of type NormalDeleter
188 : // is an optimization: instead of storing a pointer to a function that does
189 : // the deleting, we simply delete the pointer ourselves.
190 : template <class T>
191 : struct CustomDeleter<T, NormalDeleter>
192 : {
193 : T *ptr;
194 :
195 : CustomDeleter(T *p, NormalDeleter) : ptr(p) {}
196 : void execute() { delete ptr; }
197 : };
198 : // sizeof(CustomDeleter specialization) = sizeof(void*)
199 :
200 : // This class extends ExternalRefCountData and implements
201 : // the static function that deletes the object. The pointer and the
202 : // custom deleter are kept in the "extra" member so we can construct
203 : // and destruct it independently of the full structure.
204 : template <class T, typename Deleter>
205 : struct ExternalRefCountWithCustomDeleter: public ExternalRefCountData
206 : {
207 : typedef ExternalRefCountWithCustomDeleter Self;
208 : typedef ExternalRefCountData BaseClass;
209 : CustomDeleter<T, Deleter> extra;
210 :
211 : static inline void deleter(ExternalRefCountData *self)
212 : {
213 : Self *realself = static_cast<Self *>(self);
214 : realself->extra.execute();
215 :
216 : // delete the deleter too
217 : realself->extra.~CustomDeleter<T, Deleter>();
218 : }
219 : static void safetyCheckDeleter(ExternalRefCountData *self)
220 : {
221 : internalSafetyCheckRemove(self);
222 : deleter(self);
223 : }
224 :
225 : static inline Self *create(T *ptr, Deleter userDeleter, DestroyerFn actualDeleter)
226 : {
227 : Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
228 :
229 : // initialize the two sub-objects
230 : new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter);
231 : new (d) BaseClass(actualDeleter); // can't throw
232 :
233 : return d;
234 : }
235 : private:
236 : // prevent construction
237 : ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
238 : ~ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
239 : Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter)
240 : };
241 :
242 : // This class extends ExternalRefCountData and adds a "T"
243 : // member. That way, when the create() function is called, we allocate
244 : // memory for both QSharedPointer's d-pointer and the actual object being
245 : // tracked.
246 : template <class T>
247 : struct ExternalRefCountWithContiguousData: public ExternalRefCountData
248 : {
249 : typedef ExternalRefCountData Parent;
250 : T data;
251 :
252 : static void deleter(ExternalRefCountData *self)
253 : {
254 : ExternalRefCountWithContiguousData *that =
255 : static_cast<ExternalRefCountWithContiguousData *>(self);
256 : that->data.~T();
257 : }
258 : static void safetyCheckDeleter(ExternalRefCountData *self)
259 : {
260 : internalSafetyCheckRemove(self);
261 : deleter(self);
262 : }
263 :
264 : static inline ExternalRefCountData *create(T **ptr, DestroyerFn destroy)
265 : {
266 : ExternalRefCountWithContiguousData *d =
267 : static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData)));
268 :
269 : // initialize the d-pointer sub-object
270 : // leave d->data uninitialized
271 : new (d) Parent(destroy); // can't throw
272 :
273 : *ptr = &d->data;
274 : return d;
275 : }
276 :
277 : private:
278 : // prevent construction
279 : ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
280 : ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
281 : Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
282 : };
283 :
284 : #ifndef QT_NO_QOBJECT
285 : Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant);
286 : Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant);
287 : #endif
288 : } // namespace QtSharedPointer
289 :
290 : template <class T> class QSharedPointer
291 : {
292 : typedef T *QSharedPointer:: *RestrictedBool;
293 : typedef QtSharedPointer::ExternalRefCountData Data;
294 : public:
295 : typedef T Type;
296 : typedef T element_type;
297 : typedef T value_type;
298 : typedef value_type *pointer;
299 : typedef const value_type *const_pointer;
300 : typedef value_type &reference;
301 : typedef const value_type &const_reference;
302 : typedef qptrdiff difference_type;
303 :
304 : inline T *data() const { return value; }
305 : inline bool isNull() const { return !data(); }
306 : inline operator RestrictedBool() const { return isNull() ? 0 : &QSharedPointer::value; }
307 : inline bool operator !() const { return isNull(); }
308 : inline T &operator*() const { return *data(); }
309 : inline T *operator->() const { return data(); }
310 :
311 : QSharedPointer() : value(0), d(0) { }
312 : ~QSharedPointer() { deref(); }
313 :
314 : inline explicit QSharedPointer(T *ptr) : value(ptr) // noexcept
315 : { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
316 :
317 : template <typename Deleter>
318 : inline QSharedPointer(T *ptr, Deleter deleter) : value(ptr) // throws
319 : { internalConstruct(ptr, deleter); }
320 :
321 : inline QSharedPointer(const QSharedPointer<T> &other) : value(other.value), d(other.d)
322 : { if (d) ref(); }
323 : inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other)
324 : {
325 : QSharedPointer copy(other);
326 : swap(copy);
327 : return *this;
328 : }
329 : #ifdef Q_COMPILER_RVALUE_REFS
330 : inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other)
331 : {
332 : swap(other);
333 : return *this;
334 : }
335 : #endif
336 :
337 : template <class X>
338 : inline QSharedPointer(const QSharedPointer<X> &other) : value(other.value), d(other.d)
339 : { if (d) ref(); }
340 :
341 : template <class X>
342 : inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
343 : {
344 : QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
345 : internalCopy(other);
346 : return *this;
347 : }
348 :
349 : template <class X>
350 : inline QSharedPointer(const QWeakPointer<X> &other) : value(0), d(0)
351 : { *this = other; }
352 :
353 : template <class X>
354 : inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
355 : { internalSet(other.d, other.value); return *this; }
356 :
357 : inline void swap(QSharedPointer &other)
358 : { QSharedPointer<T>::internalSwap(other); }
359 :
360 : inline void reset() { clear(); }
361 : inline void reset(T *t)
362 : { QSharedPointer copy(t); swap(copy); }
363 : template <typename Deleter>
364 : inline void reset(T *t, Deleter deleter)
365 : { QSharedPointer copy(t, deleter); swap(copy); }
366 :
367 : template <class X>
368 : QSharedPointer<X> staticCast() const
369 : {
370 : return qSharedPointerCast<X, T>(*this);
371 : }
372 :
373 : template <class X>
374 : QSharedPointer<X> dynamicCast() const
375 : {
376 : return qSharedPointerDynamicCast<X, T>(*this);
377 : }
378 :
379 : template <class X>
380 : QSharedPointer<X> constCast() const
381 : {
382 : return qSharedPointerConstCast<X, T>(*this);
383 : }
384 :
385 : #ifndef QT_NO_QOBJECT
386 : template <class X>
387 : QSharedPointer<X> objectCast() const
388 : {
389 : return qSharedPointerObjectCast<X, T>(*this);
390 : }
391 : #endif
392 :
393 : inline void clear() { QSharedPointer copy; swap(copy); }
394 :
395 : QWeakPointer<T> toWeakRef() const;
396 :
397 : #if defined(Q_COMPILER_RVALUE_REFS) && defined(Q_COMPILER_VARIADIC_TEMPLATES)
398 : template <typename... Args>
399 : static QSharedPointer<T> 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 : QSharedPointer<T> result(Qt::Uninitialized);
408 : result.d = Private::create(&result.value, destroy);
409 :
410 : // now initialize the data
411 : new (result.data()) T(std::forward<Args>(arguments)...);
412 : result.d->setQObjectShared(result.value, true);
413 : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
414 : internalSafetyCheckAdd(result.d, result.value);
415 : # endif
416 : return result;
417 : }
418 : #else
419 : static inline QSharedPointer<T> create()
420 : {
421 : typedef QtSharedPointer::ExternalRefCountWithContiguousData<T> Private;
422 : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
423 : typename Private::DestroyerFn destroy = &Private::safetyCheckDeleter;
424 : # else
425 : typename Private::DestroyerFn destroy = &Private::deleter;
426 : # endif
427 : QSharedPointer<T> result(Qt::Uninitialized);
428 : result.d = Private::create(&result.value, destroy);
429 :
430 : // now initialize the data
431 : new (result.data()) T();
432 : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
433 : internalSafetyCheckAdd(result.d, result.value);
434 : # endif
435 : result.d->setQObjectShared(result.value, true);
436 : return result;
437 : }
438 : #endif
439 :
440 : private:
441 : explicit QSharedPointer(Qt::Initialization) {}
442 :
443 : inline void deref()
444 : { deref(d); }
445 : static inline void deref(Data *d)
446 : {
447 : if (!d) return;
448 : if (!d->strongref.deref()) {
449 : d->destroy();
450 : }
451 : if (!d->weakref.deref())
452 : delete d;
453 : }
454 :
455 : template <typename Deleter>
456 : inline void internalConstruct(T *ptr, Deleter deleter)
457 : {
458 : if (!ptr) {
459 : d = 0;
460 : return;
461 : }
462 :
463 : typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<T, Deleter> Private;
464 : # ifdef QT_SHAREDPOINTER_TRACK_POINTERS
465 : typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
466 : # else
467 : typename Private::DestroyerFn actualDeleter = &Private::deleter;
468 : # endif
469 : d = Private::create(ptr, deleter, actualDeleter);
470 :
471 : #ifdef QT_SHAREDPOINTER_TRACK_POINTERS
472 : internalSafetyCheckAdd(d, ptr);
473 : #endif
474 : d->setQObjectShared(ptr, true);
475 : }
476 :
477 : template <class X>
478 : inline void internalCopy(const QSharedPointer<X> &other)
479 : {
480 : Data *o = other.d;
481 : T *actual = other.value;
482 : if (o)
483 : other.ref();
484 : qSwap(d, o);
485 : qSwap(this->value, actual);
486 : deref(o);
487 : }
488 :
489 : inline void internalSwap(QSharedPointer &other)
490 : {
491 : qSwap(d, other.d);
492 : qSwap(this->value, other.value);
493 : }
494 :
495 : #if defined(Q_NO_TEMPLATE_FRIENDS)
496 : public:
497 : #else
498 : template <class X> friend class QSharedPointer;
499 : template <class X> friend class QWeakPointer;
500 : template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
501 : #endif
502 : inline void ref() const { d->weakref.ref(); d->strongref.ref(); }
503 :
504 : inline void internalSet(Data *o, T *actual)
505 : {
506 : if (o) {
507 : // increase the strongref, but never up from zero
508 : // or less (-1 is used by QWeakPointer on untracked QObject)
509 : int tmp = o->strongref.load();
510 : while (tmp > 0) {
511 : // try to increment from "tmp" to "tmp + 1"
512 : if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
513 : break; // succeeded
514 : tmp = o->strongref.load(); // failed, try again
515 : }
516 :
517 : if (tmp > 0) {
518 : o->weakref.ref();
519 : } else {
520 : o->checkQObjectShared(actual);
521 : o = 0;
522 : }
523 : }
524 :
525 : qSwap(d, o);
526 : qSwap(this->value, actual);
527 : if (!d || d->strongref.load() == 0)
528 : this->value = 0;
529 :
530 : // dereference saved data
531 : deref(o);
532 : }
533 :
534 : Type *value;
535 : Data *d;
536 : };
537 :
538 : template <class T>
539 : class QWeakPointer
540 : {
541 : typedef T *QWeakPointer:: *RestrictedBool;
542 : typedef QtSharedPointer::ExternalRefCountData Data;
543 :
544 : public:
545 : typedef T element_type;
546 : typedef T value_type;
547 : typedef value_type *pointer;
548 : typedef const value_type *const_pointer;
549 : typedef value_type &reference;
550 : typedef const value_type &const_reference;
551 : typedef qptrdiff difference_type;
552 :
553 : inline bool isNull() const { return d == 0 || d->strongref.load() == 0 || value == 0; }
554 : inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; }
555 : inline bool operator !() const { return isNull(); }
556 0 : inline T *data() const { return d == 0 || d->strongref.load() == 0 ? 0 : value; }
557 :
558 0 : inline QWeakPointer() : d(0), value(0) { }
559 0 : inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
560 :
561 : #ifndef QT_NO_QOBJECT
562 : // special constructor that is enabled only if X derives from QObject
563 : #if QT_DEPRECATED_SINCE(5, 0)
564 : template <class X>
565 : QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : 0), value(ptr)
566 : { }
567 : #endif
568 : #endif
569 :
570 : #if QT_DEPRECATED_SINCE(5, 0)
571 : template <class X>
572 : QT_DEPRECATED inline QWeakPointer &operator=(X *ptr)
573 : { return *this = QWeakPointer(ptr); }
574 : #endif
575 :
576 : inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
577 : { if (d) d->weakref.ref(); }
578 0 : inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o)
579 : {
580 0 : internalSet(o.d, o.value);
581 0 : return *this;
582 : }
583 :
584 : inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data())
585 : { if (d) d->weakref.ref();}
586 : inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o)
587 : {
588 : internalSet(o.d, o.value);
589 : return *this;
590 : }
591 :
592 : template <class X>
593 : inline QWeakPointer(const QWeakPointer<X> &o) : d(0), value(0)
594 : { *this = o; }
595 :
596 : template <class X>
597 : inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o)
598 : {
599 : // conversion between X and T could require access to the virtual table
600 : // so force the operation to go through QSharedPointer
601 : *this = o.toStrongRef();
602 : return *this;
603 : }
604 :
605 : template <class X>
606 : inline bool operator==(const QWeakPointer<X> &o) const
607 : { return d == o.d && value == static_cast<const T *>(o.value); }
608 :
609 : template <class X>
610 : inline bool operator!=(const QWeakPointer<X> &o) const
611 : { return !(*this == o); }
612 :
613 : template <class X>
614 : inline QWeakPointer(const QSharedPointer<X> &o) : d(0), value(0)
615 : { *this = o; }
616 :
617 : template <class X>
618 : inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o)
619 : {
620 : QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
621 : internalSet(o.d, o.data());
622 : return *this;
623 : }
624 :
625 : template <class X>
626 : inline bool operator==(const QSharedPointer<X> &o) const
627 : { return d == o.d; }
628 :
629 : template <class X>
630 : inline bool operator!=(const QSharedPointer<X> &o) const
631 : { return !(*this == o); }
632 :
633 : inline void clear() { *this = QWeakPointer<T>(); }
634 :
635 : inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }
636 :
637 : #if defined(QWEAKPOINTER_ENABLE_ARROW)
638 : inline T *operator->() const { return data(); }
639 : #endif
640 :
641 : private:
642 :
643 : #if defined(Q_NO_TEMPLATE_FRIENDS)
644 : public:
645 : #else
646 : template <class X> friend class QSharedPointer;
647 : template <class X> friend class QPointer;
648 : #endif
649 :
650 : template <class X>
651 0 : inline QWeakPointer &assign(X *ptr)
652 0 : { return *this = QWeakPointer<X>(ptr, true); }
653 :
654 : #ifndef QT_NO_QOBJECT
655 : template <class X>
656 0 : inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : 0), value(ptr)
657 0 : { }
658 : #endif
659 :
660 0 : inline void internalSet(Data *o, T *actual)
661 : {
662 0 : if (d == o) return;
663 0 : if (o)
664 0 : o->weakref.ref();
665 0 : if (d && !d->weakref.deref())
666 0 : delete d;
667 0 : d = o;
668 0 : value = actual;
669 : }
670 :
671 : Data *d;
672 : T *value;
673 : };
674 :
675 : //
676 : // operator== and operator!=
677 : //
678 : template <class T, class X>
679 : bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
680 : {
681 : return ptr1.data() == ptr2.data();
682 : }
683 : template <class T, class X>
684 : bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
685 : {
686 : return ptr1.data() != ptr2.data();
687 : }
688 :
689 : template <class T, class X>
690 : bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
691 : {
692 : return ptr1.data() == ptr2;
693 : }
694 : template <class T, class X>
695 : bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
696 : {
697 : return ptr1 == ptr2.data();
698 : }
699 : template <class T, class X>
700 : bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
701 : {
702 : return !(ptr1 == ptr2);
703 : }
704 : template <class T, class X>
705 : bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
706 : {
707 : return !(ptr2 == ptr1);
708 : }
709 :
710 : template <class T, class X>
711 : bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
712 : {
713 : return ptr2 == ptr1;
714 : }
715 : template <class T, class X>
716 : bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
717 : {
718 : return ptr2 != ptr1;
719 : }
720 :
721 : //
722 : // operator-
723 : //
724 : template <class T, class X>
725 : Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
726 : {
727 : return ptr1.data() - ptr2.data();
728 : }
729 : template <class T, class X>
730 : Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
731 : {
732 : return ptr1.data() - ptr2;
733 : }
734 : template <class T, class X>
735 : Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
736 : {
737 : return ptr1 - ptr2.data();
738 : }
739 :
740 : //
741 : // operator<
742 : //
743 : template <class T, class X>
744 : Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
745 : {
746 : return ptr1.data() < ptr2.data();
747 : }
748 : template <class T, class X>
749 : Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
750 : {
751 : return ptr1.data() < ptr2;
752 : }
753 : template <class T, class X>
754 : Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
755 : {
756 : return ptr1 < ptr2.data();
757 : }
758 :
759 : //
760 : // qHash
761 : //
762 : template <class T>
763 : Q_INLINE_TEMPLATE uint qHash(const QSharedPointer<T> &ptr, uint seed = 0)
764 : {
765 : return QT_PREPEND_NAMESPACE(qHash)(ptr.data(), seed);
766 : }
767 :
768 :
769 : template <class T>
770 : Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
771 : {
772 : return QWeakPointer<T>(*this);
773 : }
774 :
775 : template <class T>
776 : inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
777 : {
778 : p1.swap(p2);
779 : }
780 :
781 : QT_END_NAMESPACE
782 : namespace std {
783 : template <class T>
784 : inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2)
785 : { p1.swap(p2); }
786 : }
787 : QT_BEGIN_NAMESPACE
788 :
789 : namespace QtSharedPointer {
790 : // helper functions:
791 : template <class X, class T>
792 : Q_INLINE_TEMPLATE QSharedPointer<X> copyAndSetPointer(X *ptr, const QSharedPointer<T> &src)
793 : {
794 : QSharedPointer<X> result;
795 : result.internalSet(src.d, ptr);
796 : return result;
797 : }
798 : }
799 :
800 : // cast operators
801 : template <class X, class T>
802 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src)
803 : {
804 : X *ptr = static_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
805 : return QtSharedPointer::copyAndSetPointer(ptr, src);
806 : }
807 : template <class X, class T>
808 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src)
809 : {
810 : return qSharedPointerCast<X, T>(src.toStrongRef());
811 : }
812 :
813 : template <class X, class T>
814 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src)
815 : {
816 : X *ptr = dynamic_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
817 : if (!ptr)
818 : return QSharedPointer<X>();
819 : return QtSharedPointer::copyAndSetPointer(ptr, src);
820 : }
821 : template <class X, class T>
822 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src)
823 : {
824 : return qSharedPointerDynamicCast<X, T>(src.toStrongRef());
825 : }
826 :
827 : template <class X, class T>
828 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src)
829 : {
830 : X *ptr = const_cast<X *>(src.data()); // if you get an error in this line, the cast is invalid
831 : return QtSharedPointer::copyAndSetPointer(ptr, src);
832 : }
833 : template <class X, class T>
834 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src)
835 : {
836 : return qSharedPointerConstCast<X, T>(src.toStrongRef());
837 : }
838 :
839 : template <class X, class T>
840 : Q_INLINE_TEMPLATE
841 : QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src)
842 : {
843 : return qSharedPointerCast<X, T>(src).toWeakRef();
844 : }
845 :
846 : #ifndef QT_NO_QOBJECT
847 : template <class X, class T>
848 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src)
849 : {
850 : X *ptr = qobject_cast<X *>(src.data());
851 : return QtSharedPointer::copyAndSetPointer(ptr, src);
852 : }
853 : template <class X, class T>
854 : Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
855 : {
856 : return qSharedPointerObjectCast<X>(src.toStrongRef());
857 : }
858 :
859 : template <class X, class T>
860 : inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
861 : qobject_cast(const QSharedPointer<T> &src)
862 : {
863 : return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
864 : }
865 : template <class X, class T>
866 : inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type>
867 : qobject_cast(const QWeakPointer<T> &src)
868 : {
869 : return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
870 : }
871 :
872 : template<typename T>
873 : QWeakPointer<typename QtPrivate::QEnableIf<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::Type>
874 : qWeakPointerFromVariant(const QVariant &variant)
875 : {
876 : return QWeakPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
877 : }
878 : template<typename T>
879 : QSharedPointer<typename QtPrivate::QEnableIf<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::Type>
880 : qSharedPointerFromVariant(const QVariant &variant)
881 : {
882 : return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
883 : }
884 :
885 : #endif
886 :
887 : template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
888 : template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE);
889 :
890 :
891 : QT_END_NAMESPACE
892 :
893 : #endif
|