source: trunk/src/corelib/tools/qsharedpointer.cpp@ 135

Last change on this file since 135 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 28.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qsharedpointer.h"
43
44// to be sure we aren't causing a namespace clash:
45#include "qshareddata.h"
46
47/*!
48 \class QSharedPointer
49 \brief The QSharedPointer class holds a strong reference to a shared pointer
50 \since 4.5
51
52 \reentrant
53 \ingroup misc
54
55 The QSharedPointer is an automatic, shared pointer in C++. It
56 behaves exactly like a normal pointer for normal purposes,
57 including respect for constness.
58
59 QSharedPointer will delete the pointer it is holding when it goes
60 out of scope, provided no other QSharedPointer objects are
61 referencing it.
62
63 A QSharedPointer object can be created from a normal pointer,
64 another QSharedPointer object or by promoting a
65 QWeakPointer object to a strong reference.
66
67 \section1 Thread-Safety
68
69 QSharedPointer and QWeakPointer are thread-safe and operate
70 atomically on the pointer value. Different threads can also access
71 the same QSharedPointer or QWeakPointer object at the same time
72 without need for locking mechanisms.
73
74 It should be noted that, while the pointer value can be accessed
75 in this manner, QSharedPointer and QWeakPointer provide no
76 guarantee about the object being pointed to. Thread-safety and
77 reentrancy rules for that object still apply.
78
79 \section1 Other Pointer Classes
80
81 Qt also provides two other pointer wrapper classes: QPointer and
82 QSharedDataPointer. They are incompatible with one another, since
83 each has its very different use case.
84
85 QSharedPointer holds a shared pointer by means of an external
86 reference count (i.e., a reference counter placed outside the
87 object). Like its name indicates, the pointer value is shared
88 among all instances of QSharedPointer and QWeakPointer. The
89 contents of the object pointed to by the pointer should not
90 considered shared, however: there is only one object. For that
91 reason, QSharedPointer does not provide a way to detach or make
92 copies of the pointed object.
93
94 QSharedDataPointer, on the other hand, holds a pointer to shared
95 data (i.e., a class derived from QSharedData). It does so by means
96 of an internal reference count, placed in the QSharedData base
97 class. This class can, therefore, detach based on the type of
98 access made to the data being guarded: if it's a non-const access,
99 it creates a copy atomically for the operation to complete.
100
101 QExplicitlySharedDataPointer behaves like QSharedDataPointer,
102 except that it only detaches if
103 QExplicitlySharedDataPointer::detach() is explicitly called.
104
105 Finally, QPointer holds a pointer to a QObject-derived object, but
106 it does so weakly. QPointer is similar, in that behaviour, to
107 QWeakPointer: it does not allow you to prevent the object from
108 being destroyed. All you can do is query whether it has been
109 destroyed or not.
110
111 \sa QSharedDataPointer, QWeakPointer
112*/
113
114/*!
115 \class QWeakPointer
116 \brief The QWeakPointer class holds a weak reference to a shared pointer
117 \since 4.5
118 \reentrant
119 \ingroup misc
120
121 The QWeakPointer is an automatic weak reference to a
122 pointer in C++. It cannot be used to dereference the pointer
123 directly, but it can be used to verify if the pointer has been
124 deleted or not in another context.
125
126 QWeakPointer objects can only be created by assignment
127 from a QSharedPointer.
128
129 To access the pointer that QWeakPointer is tracking, you
130 must first create a QSharedPointer object and verify if the pointer
131 is null or not.
132
133 \sa QSharedPointer
134*/
135
136/*!
137 \fn QSharedPointer::QSharedPointer()
138
139 Creates a QSharedPointer that points to null (0).
140*/
141
142/*!
143 \fn QSharedPointer::~QSharedPointer()
144
145 Destroys this QSharedPointer object. If it is the last reference to
146 the pointer stored, this will delete the pointer as well.
147*/
148
149/*!
150 \fn QSharedPointer::QSharedPointer(T *ptr)
151
152 Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
153 becomes managed by this QSharedPointer and must not be passed to
154 another QSharedPointer object or deleted outside this object.
155*/
156
157/*!
158 \fn QSharedPointer::QSharedPointer(T *ptr, Deleter deleter)
159
160 Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
161 becomes managed by this QSharedPointer and must not be passed to
162 another QSharedPointer object or deleted outside this object.
163
164 The \a deleter paramter specifies the custom deleter for this
165 object. The custom deleter is called when the strong reference
166 count drops to 0 instead of the operator delete(). This is useful,
167 for instance, for calling deleteLater() in a QObject instead:
168
169 \code
170 static void doDeleteLater(MyObject *obj)
171 {
172 obj->deleteLater();
173 }
174
175 void otherFunction()
176 {
177 QSharedPointer<MyObject> obj =
178 QSharedPointer<MyObject>(new MyObject, doDeleteLater);
179
180 // continue using obj
181 obj.clear(); // calls obj->deleteLater();
182 }
183 \endcode
184
185 It is also possible to specify a member function directly, as in:
186 \code
187 QSharedPointer<MyObject> obj =
188 QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
189 \endcode
190
191 \sa clear()
192*/
193
194/*!
195 \fn QSharedPointer::QSharedPointer(const QSharedPointer<T> &other)
196
197 Creates a QSharedPointer object that shares \a other's pointer.
198
199 If \tt T is a derived type of the template parameter of this class,
200 QSharedPointer will perform an automatic cast. Otherwise, you will
201 get a compiler error.
202*/
203
204/*!
205 \fn QSharedPointer::QSharedPointer(const QWeakPointer<T> &other)
206
207 Creates a QSharedPointer by promoting the weak reference \a other
208 to strong reference and sharing its pointer.
209
210 If \tt T is a derived type of the template parameter of this
211 class, QSharedPointer will perform an automatic cast. Otherwise,
212 you will get a compiler error.
213*/
214
215/*!
216 \fn QSharedPointer &QSharedPointer::operator=(const QSharedPointer<T> &other)
217
218 Makes this object share \a other's pointer. The current pointer
219 reference is discarded and, if it was the last, the pointer will
220 be deleted.
221
222 If \tt T is a derived type of the template parameter of this
223 class, QSharedPointer will perform an automatic cast. Otherwise,
224 you will get a compiler error.
225*/
226
227/*!
228 \fn QSharedPointer &QSharedPointer::operator=(const QWeakPointer<T> &other)
229
230 Promotes \a other to a strong reference and makes this object
231 share a reference to the pointer referenced by it. The current pointer
232 reference is discarded and, if it was the last, the pointer will
233 be deleted.
234
235 If \tt T is a derived type of the template parameter of this
236 class, QSharedPointer will perform an automatic cast. Otherwise,
237 you will get a compiler error.
238*/
239
240/*!
241 \fn T *QSharedPointer::data() const
242
243 Returns the value of the pointer referenced by this object.
244
245 Note: do not delete the pointer returned by this function or pass
246 it to another function that could delete it, including creating
247 QSharedPointer or QWeakPointer objects.
248*/
249
250/*!
251 \fn T &QSharedPointer::operator *() const
252
253 Provides access to the shared pointer's members.
254
255 \sa isNull()
256*/
257
258/*!
259 \fn T *QSharedPointer::operator ->() const
260
261 Provides access to the shared pointer's members.
262
263 \sa isNull()
264*/
265
266/*!
267 \fn bool QSharedPointer::isNull() const
268
269 Returns true if this object is holding a reference to a null
270 pointer.
271*/
272
273/*!
274 \fn QSharedPointer::operator bool() const
275
276 Returns true if this object is not null. This function is suitable
277 for use in \tt if-constructs, like:
278
279 \code
280 if (sharedptr) { ... }
281 \endcode
282
283 \sa isNull()
284*/
285
286/*!
287 \fn bool QSharedPointer::operator !() const
288
289 Returns true if this object is null. This function is suitable
290 for use in \tt if-constructs, like:
291
292 \code
293 if (!sharedptr) { ... }
294 \endcode
295
296 \sa isNull()
297*/
298
299/*!
300 \fn QSharedPointer<X> QSharedPointer::staticCast() const
301
302 Performs a static cast from this pointer's type to \tt X and returns
303 a QSharedPointer that shares the reference. This function can be
304 used for up- and for down-casting, but is more useful for
305 up-casting.
306
307 Note: the template type \c X must have the same const and volatile
308 qualifiers as the template of this object, or the cast will
309 fail. Use constCast() if you need to drop those qualifiers.
310
311 \sa dynamicCast(), constCast(), qSharedPointerCast()
312*/
313
314/*!
315 \fn QSharedPointer<X> QSharedPointer::dynamicCast() const
316
317 Performs a dynamic cast from this pointer's type to \tt X and
318 returns a QSharedPointer that shares the reference. If this
319 function is used to up-cast, then QSharedPointer will perform a \tt
320 dynamic_cast, which means that if the object being pointed by this
321 QSharedPointer is not of type \tt X, the returned object will be
322 null.
323
324 Note: the template type \c X must have the same const and volatile
325 qualifiers as the template of this object, or the cast will
326 fail. Use constCast() if you need to drop those qualifiers.
327
328 \sa qSharedPointerDynamicCast()
329*/
330
331/*!
332 \fn QSharedPointer<X> QSharedPointer::constCast() const
333
334 Performs a \tt const_cast from this pointer's type to \tt X and returns
335 a QSharedPointer that shares the reference. This function can be
336 used for up- and for down-casting, but is more useful for
337 up-casting.
338
339 \sa isNull(), qSharedPointerConstCast()
340*/
341
342/*!
343 \fn QWeakPointer<T> QSharedPointer::toWeakRef() const
344
345 Returns a weak reference object that shares the pointer referenced
346 by this object.
347*/
348
349/*!
350 \fn void QSharedPointer::clear()
351
352 Clears this QSharedPointer object, dropping the reference that it
353 may have had to the pointer. If this was the last reference, then
354 the pointer itself will be deleted.
355*/
356
357/*!
358 \fn QWeakPointer::QWeakPointer()
359
360 Creates a QWeakPointer that points to nothing.
361*/
362
363/*!
364 \fn QWeakPointer::~QWeakPointer()
365
366 Destroys this QWeakPointer object. The pointer referenced
367 by this object will not be deleted.
368*/
369
370/*!
371 \fn QWeakPointer::QWeakPointer(const QWeakPointer<T> &other)
372
373 Creates a QWeakPointer that holds a weak reference to the
374 pointer referenced by \a other.
375
376 If \tt T is a derived type of the template parameter of this
377 class, QWeakPointer will perform an automatic cast. Otherwise,
378 you will get a compiler error.
379*/
380
381/*!
382 \fn QWeakPointer::QWeakPointer(const QSharedPointer<T> &other)
383
384 Creates a QWeakPointer that holds a weak reference to the
385 pointer referenced by \a other.
386
387 If \tt T is a derived type of the template parameter of this
388 class, QWeakPointer will perform an automatic cast. Otherwise,
389 you will get a compiler error.
390*/
391
392/*!
393 \fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other)
394
395 Makes this object share \a other's pointer. The current pointer
396 reference is discarded but is not deleted.
397
398 If \tt T is a derived type of the template parameter of this
399 class, QWeakPointer will perform an automatic cast. Otherwise,
400 you will get a compiler error.
401*/
402
403/*!
404 \fn QWeakPointer &QWeakPointer::operator=(const QSharedPointer<T> &other)
405
406 Makes this object share \a other's pointer. The current pointer
407 reference is discarded but is not deleted.
408
409 If \tt T is a derived type of the template parameter of this
410 class, QWeakPointer will perform an automatic cast. Otherwise,
411 you will get a compiler error.
412*/
413
414/*!
415 \fn bool QWeakPointer::isNull() const
416
417 Returns true if this object is holding a reference to a null
418 pointer.
419
420 Note that, due to the nature of weak references, the pointer that
421 QWeakPointer references can become null at any moment, so
422 the value returned from this function can change from false to
423 true from one call to the next.
424*/
425
426/*!
427 \fn QWeakPointer::operator bool() const
428
429 Returns true if this object is not null. This function is suitable
430 for use in \tt if-constructs, like:
431
432 \code
433 if (weakref) { ... }
434 \endcode
435
436 Note that, due to the nature of weak references, the pointer that
437 QWeakPointer references can become null at any moment, so
438 the value returned from this function can change from true to
439 false from one call to the next.
440
441 \sa isNull()
442*/
443
444/*!
445 \fn bool QWeakPointer::operator !() const
446
447 Returns true if this object is null. This function is suitable
448 for use in \tt if-constructs, like:
449
450 \code
451 if (!weakref) { ... }
452 \endcode
453
454 Note that, due to the nature of weak references, the pointer that
455 QWeakPointer references can become null at any moment, so
456 the value returned from this function can change from false to
457 true from one call to the next.
458
459 \sa isNull()
460*/
461
462/*!
463 \fn QSharedPointer<T> QWeakPointer::toStrongRef() const
464
465 Promotes this weak reference to a strong one and returns a
466 QSharedPointer object holding that reference.
467*/
468
469/*!
470 \fn void QWeakPointer::clear()
471
472 Clears this QWeakPointer object, dropping the reference that it
473 may have had to the pointer.
474*/
475
476/*!
477 \fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
478 \relates QSharedPointer
479
480 Returns true if the pointer referenced by \a ptr1 is the
481 same pointer as that referenced by \a ptr2.
482
483 If \a ptr2's template parameter is different from \a ptr1's,
484 QSharedPointer will attempt to perform an automatic \tt static_cast
485 to ensure that the pointers being compared are equal. If \a ptr2's
486 template parameter is not a base or a derived type from
487 \a ptr1's, you will get a compiler error.
488*/
489
490/*!
491 \fn bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
492 \relates QSharedPointer
493
494 Returns true if the pointer referenced by \a ptr1 is not the
495 same pointer as that referenced by \a ptr2.
496
497 If \a ptr2's template parameter is different from \a ptr1's,
498 QSharedPointer will attempt to perform an automatic \tt static_cast
499 to ensure that the pointers being compared are equal. If \a ptr2's
500 template parameter is not a base or a derived type from
501 \a ptr1's, you will get a compiler error.
502*/
503
504/*!
505 \fn bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
506 \relates QSharedPointer
507
508 Returns true if the pointer referenced by \a ptr1 is the
509 same pointer as \a ptr2.
510
511 If \a ptr2's type is different from \a ptr1's,
512 QSharedPointer will attempt to perform an automatic \tt static_cast
513 to ensure that the pointers being compared are equal. If \a ptr2's
514 type is not a base or a derived type from this
515 \a ptr1's, you will get a compiler error.
516*/
517
518/*!
519 \fn bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
520 \relates QSharedPointer
521
522 Returns true if the pointer referenced by \a ptr1 is not the
523 same pointer as \a ptr2.
524
525 If \a ptr2's type is different from \a ptr1's,
526 QSharedPointer will attempt to perform an automatic \tt static_cast
527 to ensure that the pointers being compared are equal. If \a ptr2's
528 type is not a base or a derived type from this
529 \a ptr1's, you will get a compiler error.
530*/
531
532/*!
533 \fn bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
534 \relates QSharedPointer
535
536 Returns true if the pointer \a ptr1 is the
537 same pointer as that referenced by \a ptr2.
538
539 If \a ptr2's template parameter is different from \a ptr1's type,
540 QSharedPointer will attempt to perform an automatic \tt static_cast
541 to ensure that the pointers being compared are equal. If \a ptr2's
542 template parameter is not a base or a derived type from
543 \a ptr1's type, you will get a compiler error.
544*/
545
546/*!
547 \fn bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
548 \relates QSharedPointer
549
550 Returns true if the pointer \a ptr1 is not the
551 same pointer as that referenced by \a ptr2.
552
553 If \a ptr2's template parameter is different from \a ptr1's type,
554 QSharedPointer will attempt to perform an automatic \tt static_cast
555 to ensure that the pointers being compared are equal. If \a ptr2's
556 template parameter is not a base or a derived type from
557 \a ptr1's type, you will get a compiler error.
558*/
559
560/*!
561 \fn bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
562 \relates QWeakPointer
563
564 Returns true if the pointer referenced by \a ptr1 is the
565 same pointer as that referenced by \a ptr2.
566
567 If \a ptr2's template parameter is different from \a ptr1's,
568 QSharedPointer will attempt to perform an automatic \tt static_cast
569 to ensure that the pointers being compared are equal. If \a ptr2's
570 template parameter is not a base or a derived type from
571 \a ptr1's, you will get a compiler error.
572*/
573
574/*!
575 \fn bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
576 \relates QWeakPointer
577
578 Returns true if the pointer referenced by \a ptr1 is not the
579 same pointer as that referenced by \a ptr2.
580
581 If \a ptr2's template parameter is different from \a ptr1's,
582 QSharedPointer will attempt to perform an automatic \tt static_cast
583 to ensure that the pointers being compared are equal. If \a ptr2's
584 template parameter is not a base or a derived type from
585 \a ptr1's, you will get a compiler error.
586*/
587
588/*!
589 \fn bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
590 \relates QWeakPointer
591
592 Returns true if the pointer referenced by \a ptr1 is the
593 same pointer as that referenced by \a ptr2.
594
595 If \a ptr2's template parameter is different from \a ptr1's,
596 QSharedPointer will attempt to perform an automatic \tt static_cast
597 to ensure that the pointers being compared are equal. If \a ptr2's
598 template parameter is not a base or a derived type from
599 \a ptr1's, you will get a compiler error.
600*/
601
602/*!
603 \fn bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
604 \relates QWeakPointer
605
606 Returns true if the pointer referenced by \a ptr1 is not the
607 same pointer as that referenced by \a ptr2.
608
609 If \a ptr2's template parameter is different from \a ptr1's,
610 QSharedPointer will attempt to perform an automatic \tt static_cast
611 to ensure that the pointers being compared are equal. If \a ptr2's
612 template parameter is not a base or a derived type from
613 \a ptr1's, you will get a compiler error.
614*/
615
616/*!
617 \fn QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other)
618 \relates QSharedPointer
619
620 Returns a shared pointer to the pointer held by \a other, cast to
621 type \tt X. The types \tt T and \tt X must belong to one
622 hierarchy for the \tt static_cast to succeed.
623
624 Note that \tt X must have the same cv-qualifiers (\tt const and
625 \tt volatile) that \tt T has, or the code will fail to
626 compile. Use qSharedPointerConstCast to cast away the constness.
627
628 \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
629*/
630
631/*!
632 \fn QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other)
633 \relates QSharedPointer
634 \relates QWeakPointer
635
636 Returns a shared pointer to the pointer held by \a other, cast to
637 type \tt X. The types \tt T and \tt X must belong to one
638 hierarchy for the \tt static_cast to succeed.
639
640 The \a other object is converted first to a strong reference. If
641 that conversion fails (because the object it's pointing to has
642 already been deleted), this function returns a null
643 QSharedPointer.
644
645 Note that \tt X must have the same cv-qualifiers (\tt const and
646 \tt volatile) that \tt T has, or the code will fail to
647 compile. Use qSharedPointerConstCast to cast away the constness.
648
649 \sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
650*/
651
652/*!
653 \fn QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &other)
654 \relates QSharedPointer
655
656 Returns a shared pointer to the pointer held by \a other, using a
657 dynamic cast to type \tt X to obtain an internal pointer of the
658 appropriate type. If the \tt dynamic_cast fails, the object
659 returned will be null.
660
661 Note that \tt X must have the same cv-qualifiers (\tt const and
662 \tt volatile) that \tt T has, or the code will fail to
663 compile. Use qSharedPointerConstCast to cast away the constness.
664
665 \sa QSharedPointer::dynamicCast(), qSharedPointerCast(), qSharedPointerConstCast()
666*/
667
668/*!
669 \fn QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &other)
670 \relates QSharedPointer
671 \relates QWeakPointer
672
673 Returns a shared pointer to the pointer held by \a other, using a
674 dynamic cast to type \tt X to obtain an internal pointer of the
675 appropriate type. If the \tt dynamic_cast fails, the object
676 returned will be null.
677
678 The \a other object is converted first to a strong reference. If
679 that conversion fails (because the object it's pointing to has
680 already been deleted), this function also returns a null
681 QSharedPointer.
682
683 Note that \tt X must have the same cv-qualifiers (\tt const and
684 \tt volatile) that \tt T has, or the code will fail to
685 compile. Use qSharedPointerConstCast to cast away the constness.
686
687 \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast()
688*/
689
690/*!
691 \fn QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &other)
692 \relates QSharedPointer
693
694 Returns a shared pointer to the pointer held by \a other, cast to
695 type \tt X. The types \tt T and \tt X must belong to one
696 hierarchy for the \tt const_cast to succeed. The \tt const and \tt
697 volatile differences between \tt T and \tt X are ignored.
698
699 \sa QSharedPointer::constCast(), qSharedPointerCast(), qSharedPointerDynamicCast()
700*/
701
702/*!
703 \fn QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &other)
704 \relates QSharedPointer
705 \relates QWeakPointer
706
707 Returns a shared pointer to the pointer held by \a other, cast to
708 type \tt X. The types \tt T and \tt X must belong to one
709 hierarchy for the \tt const_cast to succeed. The \tt const and
710 \tt volatile differences between \tt T and \tt X are ignored.
711
712 The \a other object is converted first to a strong reference. If
713 that conversion fails (because the object it's pointing to has
714 already been deleted), this function returns a null
715 QSharedPointer.
716
717 \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerDynamicCast()
718*/
719
720/*!
721 \fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other)
722 \relates QWeakPointer
723
724 Returns a weak pointer to the pointer held by \a other, cast to
725 type \tt X. The types \tt T and \tt X must belong to one
726 hierarchy for the \tt static_cast to succeed.
727
728 Note that \tt X must have the same cv-qualifiers (\tt const and
729 \tt volatile) that \tt T has, or the code will fail to
730 compile. Use qSharedPointerConstCast to cast away the constness.
731*/
732
733#include <qset.h>
734#include <qmutex.h>
735
736#if !defined(QT_NO_MEMBER_TEMPLATES)
737
738//# define QT_SHARED_POINTER_BACKTRACE_SUPPORT
739# ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT
740# if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE)
741# define BACKTRACE_SUPPORTED
742# elif defined(Q_OS_MACX)
743# define BACKTRACE_SUPPORTED
744# endif
745# endif
746
747# if !defined(BACKTRACE_SUPPORTED)
748// Dummy implementation of the functions.
749// Using QHashDummyValue also means that the QHash below is actually a QSet
750typedef QT_PREPEND_NAMESPACE(QHashDummyValue) Backtrace;
751
752static inline Backtrace saveBacktrace() { return Backtrace(); }
753static inline void printBacktrace(Backtrace) { }
754
755# else
756# include <sys/types.h>
757# include <execinfo.h>
758# include <stdio.h>
759# include <unistd.h>
760# include <sys/wait.h>
761
762typedef QT_PREPEND_NAMESPACE(QByteArray) Backtrace;
763
764static inline Backtrace saveBacktrace() __attribute__((always_inline));
765static inline Backtrace saveBacktrace()
766{
767 static const int maxFrames = 32;
768
769 Backtrace stacktrace;
770 stacktrace.resize(sizeof(void*) * maxFrames);
771 int stack_size = backtrace((void**)stacktrace.data(), maxFrames);
772 stacktrace.resize(sizeof(void*) * stack_size);
773
774 return stacktrace;
775}
776
777static void printBacktrace(Backtrace stacktrace)
778{
779 void *const *stack = (void *const *)stacktrace.constData();
780 int stack_size = stacktrace.size() / sizeof(void*);
781 char **stack_symbols = backtrace_symbols(stack, stack_size);
782
783 int filter[2];
784 pid_t child = -1;
785 if (pipe(filter) != -1)
786 child = fork();
787 if (child == 0) {
788 // child process
789 dup2(fileno(stderr), fileno(stdout));
790 dup2(filter[0], fileno(stdin));
791 close(filter[0]);
792 close(filter[1]);
793 execlp("c++filt", "c++filt", "-n", NULL);
794
795 // execlp failed
796 execl("/bin/cat", "/bin/cat", NULL);
797 _exit(127);
798 }
799
800 // parent process
801 close(filter[0]);
802 FILE *output;
803 if (child == -1) {
804 // failed forking
805 close(filter[1]);
806 output = stderr;
807 } else {
808 output = fdopen(filter[1], "w");
809 }
810
811 fprintf(stderr, "Backtrace of the first creation (most recent frame first):\n");
812 for (int i = 0; i < stack_size; ++i) {
813 if (strlen(stack_symbols[i]))
814 fprintf(output, "#%-2d %s\n", i, stack_symbols[i]);
815 else
816 fprintf(output, "#%-2d %p\n", i, stack[i]);
817 }
818
819 if (child != -1) {
820 fclose(output);
821 waitpid(child, 0, 0);
822 }
823}
824# endif // BACKTRACE_SUPPORTED
825
826namespace {
827 QT_USE_NAMESPACE
828 class KnownPointers
829 {
830 public:
831 QMutex mutex;
832 QHash<void *, Backtrace> values;
833 };
834}
835
836Q_GLOBAL_STATIC(KnownPointers, knownPointers)
837
838QT_BEGIN_NAMESPACE
839
840/*!
841 \internal
842*/
843void QtSharedPointer::internalSafetyCheckAdd(const volatile void *ptr)
844{
845 KnownPointers *const kp = knownPointers();
846 if (!kp)
847 return; // end-game: the application is being destroyed already
848
849 QMutexLocker lock(&kp->mutex);
850 void *actual = const_cast<void*>(ptr);
851 if (kp->values.contains(actual)) {
852 printBacktrace(knownPointers()->values.value(actual));
853 qFatal("QSharedPointerData: internal self-check failed: pointer %p was already tracked "
854 "by another QSharedPointerData object", actual);
855 }
856
857 kp->values.insert(actual, saveBacktrace());
858}
859
860/*!
861 \internal
862*/
863void QtSharedPointer::internalSafetyCheckRemove(const volatile void *ptr)
864{
865 KnownPointers *const kp = knownPointers();
866 if (!kp)
867 return; // end-game: the application is being destroyed already
868
869 QMutexLocker lock(&kp->mutex);
870 void *actual = const_cast<void*>(ptr);
871 kp->values.remove(actual);
872}
873
874QT_END_NAMESPACE
875
876#endif
Note: See TracBrowser for help on using the repository browser.