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