author | Eckhart Koeppen <eckhart.koppen@nokia.com> |
Mon, 19 Apr 2010 10:15:19 +0300 | |
branch | RCL_3 |
changeset 9 | b5b118452c7d |
parent 5 | d3bac044e0f0 |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 4 |
** All rights reserved. |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 |
** |
|
7 |
** This file is part of the QtCore module of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** No Commercial Usage |
|
11 |
** This file contains pre-release code and may not be distributed. |
|
12 |
** You may use this file in accordance with the terms and conditions |
|
13 |
** contained in the Technology Preview License Agreement accompanying |
|
14 |
** this package. |
|
15 |
** |
|
16 |
** GNU Lesser General Public License Usage |
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 |
** General Public License version 2.1 as published by the Free Software |
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 |
** packaging of this file. Please review the following information to |
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 |
** |
|
24 |
** In addition, as a special exception, Nokia gives you certain additional |
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 |
** |
|
28 |
** If you have questions regarding the use of this file, please contact |
|
29 |
** Nokia at qt-info@nokia.com. |
|
30 |
** |
|
31 |
** |
|
32 |
** |
|
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
|
37 |
** |
|
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 |
||
54 |
The QSharedPointer is an automatic, shared pointer in C++. It |
|
55 |
behaves exactly like a normal pointer for normal purposes, |
|
56 |
including respect for constness. |
|
57 |
||
58 |
QSharedPointer will delete the pointer it is holding when it goes |
|
59 |
out of scope, provided no other QSharedPointer objects are |
|
60 |
referencing it. |
|
61 |
||
62 |
A QSharedPointer object can be created from a normal pointer, |
|
63 |
another QSharedPointer object or by promoting a |
|
64 |
QWeakPointer object to a strong reference. |
|
65 |
||
66 |
\section1 Thread-Safety |
|
67 |
||
68 |
QSharedPointer and QWeakPointer are thread-safe and operate |
|
69 |
atomically on the pointer value. Different threads can also access |
|
70 |
the same QSharedPointer or QWeakPointer object at the same time |
|
71 |
without need for locking mechanisms. |
|
72 |
||
73 |
It should be noted that, while the pointer value can be accessed |
|
74 |
in this manner, QSharedPointer and QWeakPointer provide no |
|
75 |
guarantee about the object being pointed to. Thread-safety and |
|
76 |
reentrancy rules for that object still apply. |
|
77 |
||
78 |
\section1 Other Pointer Classes |
|
79 |
||
80 |
Qt also provides two other pointer wrapper classes: QPointer and |
|
81 |
QSharedDataPointer. They are incompatible with one another, since |
|
82 |
each has its very different use case. |
|
83 |
||
84 |
QSharedPointer holds a shared pointer by means of an external |
|
85 |
reference count (i.e., a reference counter placed outside the |
|
86 |
object). Like its name indicates, the pointer value is shared |
|
87 |
among all instances of QSharedPointer and QWeakPointer. The |
|
88 |
contents of the object pointed to by the pointer should not |
|
89 |
considered shared, however: there is only one object. For that |
|
90 |
reason, QSharedPointer does not provide a way to detach or make |
|
91 |
copies of the pointed object. |
|
92 |
||
93 |
QSharedDataPointer, on the other hand, holds a pointer to shared |
|
94 |
data (i.e., a class derived from QSharedData). It does so by means |
|
95 |
of an internal reference count, placed in the QSharedData base |
|
96 |
class. This class can, therefore, detach based on the type of |
|
97 |
access made to the data being guarded: if it's a non-const access, |
|
98 |
it creates a copy atomically for the operation to complete. |
|
99 |
||
100 |
QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except |
|
101 |
that it only detaches if QExplicitlySharedDataPointer::detach() is |
|
102 |
explicitly called (hence the name). |
|
103 |
||
104 |
QScopedPointer simply holds a pointer to a heap allocated object and |
|
105 |
deletes it in its destructor. This class is useful when an object needs to |
|
106 |
be heap allocated and deleted, but no more. QScopedPointer is lightweight, |
|
107 |
it makes no use of additional structure or reference counting. |
|
108 |
||
109 |
Finally, QPointer holds a pointer to a QObject-derived object, but it |
|
110 |
does so weakly. QPointer can be replaced by QWeakPointer in almost all |
|
111 |
cases, since they have the same functionality. See |
|
112 |
\l{QWeakPointer#tracking-qobject} for more information. |
|
113 |
||
114 |
\section1 Optional pointer tracking |
|
115 |
||
116 |
A feature of QSharedPointer that can be enabled at compile-time for |
|
117 |
debugging purposes is a pointer tracking mechanism. When enabled, |
|
118 |
QSharedPointer registers in a global set all the pointers that it tracks. |
|
119 |
This allows one to catch mistakes like assigning the same pointer to two |
|
120 |
QSharedPointer objects. |
|
121 |
||
122 |
This function is enabled by defining the \tt{QT_SHAREDPOINTER_TRACK_POINTERS} |
|
123 |
macro before including the QSharedPointer header. |
|
124 |
||
125 |
It is safe to use this feature even with code compiled without the |
|
126 |
feature. QSharedPointer will ensure that the pointer is removed from the |
|
127 |
tracker even from code compiled without pointer tracking. |
|
128 |
||
129 |
Note, however, that the pointer tracking feature has limitations on |
|
130 |
multiple- or virtual-inheritance (that is, in cases where two different |
|
131 |
pointer addresses can refer to the same object). In that case, if a |
|
132 |
pointer is cast to a different type and its value changes, |
|
5
d3bac044e0f0
Revision: 201007
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
4
diff
changeset
|
133 |
QSharedPointer's pointer tracking mechanism may fail to detect that the |
0 | 134 |
object being tracked is the same. |
135 |
||
136 |
\omit |
|
137 |
\secton1 QSharedPointer internals |
|
138 |
||
139 |
QSharedPointer is in reality implemented by two ancestor classes: |
|
140 |
QtSharedPointer::Basic and QtSharedPointer::ExternalRefCount. The reason |
|
141 |
for having that split is now mostly legacy: in the beginning, |
|
142 |
QSharedPointer was meant to support both internal reference counting and |
|
143 |
external reference counting. |
|
144 |
||
145 |
QtSharedPointer::Basic implements the basic functionality that is shared |
|
146 |
between internal- and external-reference counting. That is, it's mostly |
|
147 |
the accessor functions into QSharedPointer. Those are all inherited by |
|
148 |
QSharedPointer, which adds another level of shared functionality (the |
|
149 |
constructors and assignment operators). The Basic class has one member |
|
150 |
variable, which is the actual pointer being tracked. |
|
151 |
||
152 |
QtSharedPointer::ExternalRefCount implements the actual reference |
|
153 |
counting and introduces the d-pointer for QSharedPointer. That d-pointer |
|
154 |
itself is shared with with other QSharedPointer objects as well as |
|
155 |
QWeakPointer. |
|
156 |
||
157 |
The reason for keeping the pointer value itself outside the d-pointer is |
|
158 |
because of multiple inheritance needs. If you have two QSharedPointer |
|
159 |
objects of different pointer types, but pointing to the same object in |
|
160 |
memory, it could happen that the pointer values are different. The \tt |
|
161 |
differentPointers autotest exemplifies this problem. The same thing could |
|
162 |
happen in the case of virtual inheritance: a pointer of class matching |
|
163 |
the virtual base has different address compared to the pointer of the |
|
164 |
complete object. See the \tt virtualBaseDifferentPointers autotest for |
|
165 |
this problem. |
|
166 |
||
167 |
The d pointer is of type QtSharedPointer::ExternalRefCountData for simple |
|
168 |
QSharedPointer objects, but could be of a derived type in some cases. It |
|
169 |
is basically a reference-counted reference-counter. |
|
170 |
||
171 |
\section2 d-pointer |
|
172 |
\section3 QtSharedPointer::ExternalRefCountData |
|
173 |
||
174 |
This class is basically a reference-counted reference-counter. It has two |
|
175 |
members: \tt strongref and \tt weakref. The strong reference counter is |
|
176 |
controlling the lifetime of the object tracked by QSharedPointer. a |
|
177 |
positive value indicates that the object is alive. It's also the number |
|
178 |
of QSharedObject instances that are attached to this Data. |
|
179 |
||
180 |
When the strong reference count decreases to zero, the object is deleted |
|
181 |
(see below for information on custom deleters). The strong reference |
|
182 |
count can also exceptionally be -1, indicating that there are no |
|
183 |
QSharedPointers attached to an object, which is tracked too. The only |
|
184 |
case where this is possible is that of |
|
185 |
\l{QWeakPointer#tracking-qobject}{QWeakPointers tracking a QObject}. |
|
186 |
||
187 |
The weak reference count controls the lifetime of the d-pointer itself. |
|
188 |
It can be thought of as an internal/intrusive reference count for |
|
189 |
ExternalRefCountData itself. This count is equal to the number of |
|
190 |
QSharedPointers and QWeakPointers that are tracking this object. (In case |
|
191 |
the object tracked derives from QObject, this number is increased by 1, |
|
192 |
since QObjectPrivate tracks it too). |
|
193 |
||
194 |
ExternalRefCountData is a virtual class: it has a virtual destructor and |
|
195 |
a virtual destroy() function. The destroy() function is supposed to |
|
196 |
delete the object being tracked and return true if it does so. Otherwise, |
|
197 |
it returns false to indicate that the caller must simply call delete. |
|
198 |
This allows the normal use-case of QSharedPointer without custom deleters |
|
199 |
to use only one 12- or 16-byte (depending on whether it's a 32- or 64-bit |
|
200 |
architecture) external descriptor structure, without paying the price for |
|
201 |
the custom deleter that it isn't using. |
|
202 |
||
203 |
\section3 QtSharedPointer::ExternalRefCountDataWithDestroyFn |
|
204 |
||
205 |
This class is not used directly, per se. It only exists to enable the two |
|
206 |
classes that derive from it. It adds one member variable, which is a |
|
207 |
pointer to a function (which returns void and takes an |
|
208 |
ExternalRefCountData* as a parameter). It also overrides the destroy() |
|
209 |
function: it calls that function pointer with \tt this as parameter, and |
|
210 |
returns true. |
|
211 |
||
212 |
That means when ExternalRefCountDataWithDestroyFn is used, the \tt |
|
213 |
destroyer field must be set to a valid function that \b will delete the |
|
214 |
object tracked. |
|
215 |
||
216 |
This class also adds an operator delete function to ensure that simply |
|
217 |
calls the global operator delete. That should be the behaviour in all |
|
218 |
compilers already, but to be on the safe side, this class ensures that no |
|
219 |
funny business happens. |
|
220 |
||
221 |
On a 32-bit architecture, this class is 16 bytes in size, whereas it's 24 |
|
222 |
bytes on 64-bit. (On Itanium where function pointers contain the global |
|
223 |
pointer, it can be 32 bytes). |
|
224 |
||
225 |
\section3 QtSharedPointer::ExternalRefCountWithCustomDeleter |
|
226 |
||
227 |
This class derives from ExternalRefCountDataWithDestroyFn and is a |
|
228 |
template class. As template parameters, it has the type of the pointer |
|
229 |
being tracked (\tt T) and a \tt Deleter, which is anything. It adds two |
|
230 |
fields to its parent class, matching those template parameters: a member |
|
231 |
of type \tt Deleter and a member of type \tt T*. |
|
232 |
||
233 |
The purpose of this class is to store the pointer to be deleted and the |
|
234 |
deleter code along with the d-pointer. This allows the last strong |
|
235 |
reference to call any arbitrary function that disposes of the object. For |
|
236 |
example, this allows calling QObject::deleteLater() on a given object. |
|
237 |
The pointer to the object is kept here to avoid the extra cost of keeping |
|
238 |
the deleter in the generic case. |
|
239 |
||
240 |
This class is never instantiated directly: the constructors and |
|
241 |
destructor are private. Only the create() function may be called to |
|
242 |
return an object of this type. See below for construction details. |
|
243 |
||
244 |
The size of this class depends on the size of \tt Deleter. If it's an |
|
245 |
empty functor (i.e., no members), ABIs generally assign it the size of 1. |
|
246 |
But given that it's followed by a pointer, up to 3 or 7 padding bytes may |
|
247 |
be inserted: in that case, the size of this class is 16+4+4 = 24 bytes on |
|
248 |
32-bit architectures, or 24+8+8 = 40 bytes on 64-bit architectures (48 |
|
249 |
bytes on Itanium with global pointers stored). If \tt Deleter is a |
|
250 |
function pointer, the size should be the same as the empty structure |
|
251 |
case, except for Itanium where it may be 56 bytes due to another global |
|
252 |
pointer. If \tt Deleter is a pointer to a member function (PMF), the size |
|
253 |
will be even bigger and will depend on the ABI. For architectures using |
|
254 |
the Itanium C++ ABI, a PMF is twice the size of a normal pointer, or 24 |
|
255 |
bytes on Itanium itself. In that case, the size of this structure will be |
|
256 |
16+8+4 = 28 bytes on 32-bit architectures, 24+16+8 = 48 bytes on 64-bit, |
|
257 |
and 32+24+8 = 64 bytes on Itanium. |
|
258 |
||
259 |
(Values for Itanium consider an LP64 architecture; for ILP32, pointers |
|
260 |
are 32-bit in length, function pointers are 64-bit and PMF are 96-bit, so |
|
261 |
the sizes are slightly less) |
|
262 |
||
263 |
\section3 QtSharedPointer::ExternalRefCountWithContiguousData |
|
264 |
||
265 |
This class also derives from ExternalRefCountDataWithDestroyFn and it is |
|
266 |
also a template class. The template parameter is the type \tt T of the |
|
267 |
class which QSharedPointer tracks. It adds only one member to its parent, |
|
268 |
which is of type \tt T (the actual type, not a pointer to it). |
|
269 |
||
270 |
The purpose of this class is to lay the \tt T object out next to the |
|
271 |
reference counts, saving one memory allocation per shared pointer. This |
|
272 |
is particularly interesting for small \tt T or for the cases when there |
|
273 |
are few if any QWeakPointer tracking the object. This class exists to |
|
274 |
implement the QSharedPointer::create() call. |
|
275 |
||
276 |
Like ExternalRefCountWithCustomDeleter, this class is never instantiated |
|
277 |
directly. This class also provides a create() member that returns the |
|
278 |
pointer, and hides its constructors and destructor. (With C++0x, we'd |
|
279 |
delete them). |
|
280 |
||
281 |
The size of this class depends on the size of \tt T. |
|
282 |
||
283 |
\section3 Instantiating ExternalRefCountWithCustomDeleter and ExternalRefCountWithContiguousData |
|
284 |
||
285 |
Like explained above, these classes have private constructors. Moreover, |
|
286 |
they are not defined anywhere, so trying to call \tt{new ClassType} would |
|
287 |
result in a compilation or linker error. Instead, these classes must be |
|
288 |
constructed via their create() methods. |
|
289 |
||
290 |
Instead of instantiating the class by the normal way, the create() method |
|
291 |
calls \tt{operator new} directly with the size of the class, then calls |
|
292 |
the parent class's constructor only (ExternalRefCountDataWithDestroyFn). |
|
293 |
This ensures that the inherited members are initialised properly, as well |
|
294 |
as the virtual table pointer, which must point to |
|
295 |
ExternalRefCountDataWithDestroyFn's virtual table. That way, we also |
|
296 |
ensure that the virtual destructor being called is |
|
297 |
ExternalRefCountDataWithDestroyFn's. |
|
298 |
||
299 |
After initialising the base class, the |
|
300 |
ExternalRefCountWithCustomDeleter::create() function initialises the new |
|
301 |
members directly, by using the placement \tt{operator new}. In the case |
|
302 |
of the ExternalRefCountWithContiguousData::create() function, the address |
|
303 |
to the still-uninitialised \tt T member is saved for the callee to use. |
|
304 |
The member is only initialised in QSharedPointer::create(), so that we |
|
305 |
avoid having many variants of the internal functions according to the |
|
306 |
arguments in use for calling the constructor. |
|
307 |
||
308 |
When initialising the parent class, the create() functions pass the |
|
309 |
address of the static deleter() member function. That is, when the |
|
310 |
virtual destroy() is called by QSharedPointer, the deleter() functions |
|
311 |
are called instead. These functiosn static_cast the ExternalRefCountData* |
|
312 |
parameter to their own type and execute their deletion: for the |
|
313 |
ExternalRefCountWithCustomDeleter::deleter() case, it runs the user's |
|
314 |
custom deleter, then destroys the deleter; for |
|
315 |
ExternalRefCountWithContiguousData::deleter, it simply calls the \tt T |
|
316 |
destructor directly. |
|
317 |
||
318 |
By not calling the constructor of the derived classes, we avoid |
|
319 |
instantiating their virtual tables. Since these classes are |
|
320 |
template-based, there would be one virtual table per \tt T and \tt |
|
321 |
Deleter type. (This is what Qt 4.5 did) |
|
322 |
||
323 |
Instead, only one non-inline function is required per template, which is |
|
324 |
the deleter() static member. All the other functions can be inlined. |
|
325 |
What's more, the address of deleter() is calculated only in code, which |
|
326 |
can be resolved at link-time if the linker can determine that the |
|
327 |
function lies in the current application or library module (since these |
|
328 |
classes are not exported, that is the case for Windows or for builds with |
|
329 |
\tt{-fvisibility=hidden}). |
|
330 |
||
331 |
In contrast, a virtual table would require at least 3 relocations to be |
|
332 |
resolved at module load-time, per module where these classes are used. |
|
333 |
(In the Itanium C++ ABI, there would be more relocations, due to the |
|
334 |
RTTI) |
|
335 |
||
336 |
\section3 Modifications due to pointer-tracking |
|
337 |
||
338 |
To ensure that pointers created with pointer-tracking enabled get |
|
339 |
un-tracked when destroyed, even if destroyed by code compiled without the |
|
340 |
feature, QSharedPointer modifies slightly the instructions of the |
|
341 |
previous sections. |
|
342 |
||
343 |
When ExternalRefCountWithCustomDeleter or |
|
344 |
ExternalRefCountWithContiguousData are used, their create() functions |
|
345 |
will set the ExternalRefCountDataWithDestroyFn::destroyer function |
|
346 |
pointer to safetyCheckDeleter() instead. These static member functions |
|
347 |
simply call internalSafetyCheckRemove2() before passing control to the |
|
348 |
normal deleter() function. |
|
349 |
||
350 |
If neither custom deleter nor QSharedPointer::create() are used, then |
|
351 |
QSharedPointer uses a custom deleter of its own: the normalDeleter() |
|
352 |
function, which simply calls \tt delete. By using a custom deleter, the |
|
353 |
safetyCheckDeleter() procedure described above kicks in. |
|
354 |
||
355 |
\endomit |
|
356 |
||
357 |
\sa QSharedDataPointer, QWeakPointer, QScopedPointer |
|
358 |
*/ |
|
359 |
||
360 |
/*! |
|
361 |
\class QWeakPointer |
|
362 |
\brief The QWeakPointer class holds a weak reference to a shared pointer |
|
363 |
\since 4.5 |
|
364 |
\reentrant |
|
365 |
||
366 |
The QWeakPointer is an automatic weak reference to a |
|
367 |
pointer in C++. It cannot be used to dereference the pointer |
|
368 |
directly, but it can be used to verify if the pointer has been |
|
369 |
deleted or not in another context. |
|
370 |
||
371 |
QWeakPointer objects can only be created by assignment from a |
|
372 |
QSharedPointer. The exception is pointers derived from QObject: in that |
|
373 |
case, QWeakPointer serves as a replacement to QPointer. |
|
374 |
||
375 |
It's important to note that QWeakPointer provides no automatic casting |
|
376 |
operators to prevent mistakes from happening. Even though QWeakPointer |
|
377 |
tracks a pointer, it should not be considered a pointer itself, since it |
|
378 |
doesn't guarantee that the pointed object remains valid. |
|
379 |
||
380 |
Therefore, to access the pointer that QWeakPointer is tracking, you must |
|
381 |
first promote it to QSharedPointer and verify if the resulting object is |
|
382 |
null or not. QSharedPointer guarantees that the object isn't deleted, so |
|
383 |
if you obtain a non-null object, you may use the pointer. See |
|
384 |
QWeakPointer::toStrongRef() for more an example. |
|
385 |
||
386 |
QWeakPointer also provides the QWeakPointer::data() method that returns |
|
387 |
the tracked pointer without ensuring that it remains valid. This function |
|
388 |
is provided if you can guarantee by external means that the object will |
|
389 |
not get deleted (or if you only need the pointer value) and the cost of |
|
390 |
creating a QSharedPointer using toStrongRef() is too high. |
|
391 |
||
392 |
That function can also be used to obtain the tracked pointer for |
|
393 |
QWeakPointers that cannot be promoted to QSharedPointer, such as those |
|
394 |
created directly from a QObject pointer (not via QSharedPointer). |
|
395 |
||
396 |
\section1 Tracking QObject |
|
397 |
||
398 |
QWeakPointer can be used to track deletion classes derives from QObject, |
|
399 |
even if they are not managed by QSharedPointer. When used in that role, |
|
400 |
QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer |
|
401 |
is also more efficient than QPointer, so it should be preferred in all |
|
402 |
new code. |
|
403 |
||
404 |
To do that, QWeakPointer provides a special constructor that is only |
|
405 |
available if the template parameter \tt T is either QObject or a class |
|
406 |
deriving from it. Trying to use that constructor if \tt T does not derive |
|
407 |
from QObject will result in compilation errors. |
|
408 |
||
409 |
To obtain the QObject being tracked by QWeakPointer, you must use the |
|
410 |
QWeakPointer::data() function, but only if you can guarantee that the |
|
411 |
object cannot get deleted by another context. It should be noted that |
|
412 |
QPointer had the same constraint, so use of QWeakPointer forces you to |
|
413 |
consider whether the pointer is still valid. |
|
414 |
||
415 |
QObject-derived classes can only be deleted in the thread they have |
|
416 |
affinity to (which is the thread they were created in or moved to, using |
|
417 |
QObject::moveToThread()). In special, QWidget-derived classes cannot be |
|
418 |
created in non-GUI threads nor moved there. Therefore, guaranteeing that |
|
419 |
the tracked QObject has affinity to the current thread is enough to also |
|
420 |
guarantee that it won't be deleted asynchronously. |
|
421 |
||
422 |
Note that QWeakPointer's size and data layout do not match QPointer, so |
|
423 |
it cannot replace that class in a binary-compatible manner. |
|
424 |
||
425 |
Care must also be taken with QWeakPointers created directly from QObject |
|
426 |
pointers when dealing with code that was compiled with Qt versions prior |
|
427 |
to 4.6. Those versions may not track the reference counters correctly, so |
|
428 |
QWeakPointers created from QObject should never be passed to code that |
|
429 |
hasn't been recompiled. |
|
430 |
||
431 |
\omit |
|
432 |
\secton1 QWeakPointer internals |
|
433 |
||
434 |
QWeakPointer shares most of its internal functionality with |
|
435 |
\l{QSharedPointer#qsharedpointer-internals}{QSharedPointer}, so see that |
|
436 |
class's internal documentation for more information. |
|
437 |
||
438 |
QWeakPointer requires an external reference counter in order to operate. |
|
439 |
Therefore, it is incompatible by design with \l QSharedData-derived |
|
440 |
classes. |
|
441 |
||
442 |
It has a special QObject constructor, which works by calling |
|
443 |
QtSharedPointer::ExternalRefCountData::getAndRef, which retrieves the |
|
444 |
d-pointer from QObjectPrivate. If one isn't set yet, that function |
|
445 |
creates the d-pointer and atomically sets it. |
|
446 |
||
447 |
If getAndRef needs to create a d-pointer, it sets the strongref to -1, |
|
448 |
indicating that the QObject is not shared: QWeakPointer is used only to |
|
449 |
determine whether the QObject has been deleted. In that case, it cannot |
|
450 |
be upgraded to QSharedPointer (see the previous section). |
|
451 |
||
452 |
\endomit |
|
453 |
||
454 |
\sa QSharedPointer, QScopedPointer |
|
455 |
*/ |
|
456 |
||
457 |
/*! |
|
458 |
\fn QSharedPointer::QSharedPointer() |
|
459 |
||
460 |
Creates a QSharedPointer that points to null (0). |
|
461 |
*/ |
|
462 |
||
463 |
/*! |
|
464 |
\fn QSharedPointer::~QSharedPointer() |
|
465 |
||
466 |
Destroys this QSharedPointer object. If it is the last reference to |
|
467 |
the pointer stored, this will delete the pointer as well. |
|
468 |
*/ |
|
469 |
||
470 |
/*! |
|
471 |
\fn QSharedPointer::QSharedPointer(T *ptr) |
|
472 |
||
473 |
Creates a QSharedPointer that points to \a ptr. The pointer \a ptr |
|
474 |
becomes managed by this QSharedPointer and must not be passed to |
|
475 |
another QSharedPointer object or deleted outside this object. |
|
476 |
*/ |
|
477 |
||
478 |
/*! |
|
479 |
\fn QSharedPointer::QSharedPointer(T *ptr, Deleter deleter) |
|
480 |
||
481 |
Creates a QSharedPointer that points to \a ptr. The pointer \a ptr |
|
482 |
becomes managed by this QSharedPointer and must not be passed to |
|
483 |
another QSharedPointer object or deleted outside this object. |
|
484 |
||
485 |
The \a deleter paramter specifies the custom deleter for this |
|
486 |
object. The custom deleter is called when the strong reference |
|
487 |
count drops to 0 instead of the operator delete(). This is useful, |
|
488 |
for instance, for calling deleteLater() in a QObject instead: |
|
489 |
||
490 |
\code |
|
491 |
static void doDeleteLater(MyObject *obj) |
|
492 |
{ |
|
493 |
obj->deleteLater(); |
|
494 |
} |
|
495 |
||
496 |
void otherFunction() |
|
497 |
{ |
|
498 |
QSharedPointer<MyObject> obj = |
|
499 |
QSharedPointer<MyObject>(new MyObject, doDeleteLater); |
|
500 |
||
501 |
// continue using obj |
|
502 |
obj.clear(); // calls obj->deleteLater(); |
|
503 |
} |
|
504 |
\endcode |
|
505 |
||
506 |
It is also possible to specify a member function directly, as in: |
|
507 |
\code |
|
508 |
QSharedPointer<MyObject> obj = |
|
509 |
QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater); |
|
510 |
\endcode |
|
511 |
||
512 |
\sa clear() |
|
513 |
*/ |
|
514 |
||
515 |
/*! |
|
516 |
\fn QSharedPointer::QSharedPointer(const QSharedPointer<T> &other) |
|
517 |
||
518 |
Creates a QSharedPointer object that shares \a other's pointer. |
|
519 |
||
520 |
If \tt T is a derived type of the template parameter of this class, |
|
521 |
QSharedPointer will perform an automatic cast. Otherwise, you will |
|
522 |
get a compiler error. |
|
523 |
*/ |
|
524 |
||
525 |
/*! |
|
526 |
\fn QSharedPointer::QSharedPointer(const QWeakPointer<T> &other) |
|
527 |
||
528 |
Creates a QSharedPointer by promoting the weak reference \a other |
|
529 |
to strong reference and sharing its pointer. |
|
530 |
||
531 |
If \tt T is a derived type of the template parameter of this |
|
532 |
class, QSharedPointer will perform an automatic cast. Otherwise, |
|
533 |
you will get a compiler error. |
|
534 |
||
535 |
\sa QWeakPointer::toStrongRef() |
|
536 |
*/ |
|
537 |
||
538 |
/*! |
|
539 |
\fn QSharedPointer &QSharedPointer::operator=(const QSharedPointer<T> &other) |
|
540 |
||
541 |
Makes this object share \a other's pointer. The current pointer |
|
542 |
reference is discarded and, if it was the last, the pointer will |
|
543 |
be deleted. |
|
544 |
||
545 |
If \tt T is a derived type of the template parameter of this |
|
546 |
class, QSharedPointer will perform an automatic cast. Otherwise, |
|
547 |
you will get a compiler error. |
|
548 |
*/ |
|
549 |
||
550 |
/*! |
|
551 |
\fn QSharedPointer &QSharedPointer::operator=(const QWeakPointer<T> &other) |
|
552 |
||
553 |
Promotes \a other to a strong reference and makes this object |
|
554 |
share a reference to the pointer referenced by it. The current pointer |
|
555 |
reference is discarded and, if it was the last, the pointer will |
|
556 |
be deleted. |
|
557 |
||
558 |
If \tt T is a derived type of the template parameter of this |
|
559 |
class, QSharedPointer will perform an automatic cast. Otherwise, |
|
560 |
you will get a compiler error. |
|
561 |
*/ |
|
562 |
||
563 |
/*! |
|
564 |
\fn T *QSharedPointer::data() const |
|
565 |
||
566 |
Returns the value of the pointer referenced by this object. |
|
567 |
||
568 |
Note: do not delete the pointer returned by this function or pass |
|
569 |
it to another function that could delete it, including creating |
|
570 |
QSharedPointer or QWeakPointer objects. |
|
571 |
*/ |
|
572 |
||
573 |
/*! |
|
574 |
\fn T &QSharedPointer::operator *() const |
|
575 |
||
576 |
Provides access to the shared pointer's members. |
|
577 |
||
578 |
\sa isNull() |
|
579 |
*/ |
|
580 |
||
581 |
/*! |
|
582 |
\fn T *QSharedPointer::operator ->() const |
|
583 |
||
584 |
Provides access to the shared pointer's members. |
|
585 |
||
586 |
\sa isNull() |
|
587 |
*/ |
|
588 |
||
589 |
/*! |
|
590 |
\fn bool QSharedPointer::isNull() const |
|
591 |
||
592 |
Returns true if this object is holding a reference to a null |
|
593 |
pointer. |
|
594 |
*/ |
|
595 |
||
596 |
/*! |
|
597 |
\fn QSharedPointer::operator bool() const |
|
598 |
||
599 |
Returns true if this object is not null. This function is suitable |
|
600 |
for use in \tt if-constructs, like: |
|
601 |
||
602 |
\code |
|
603 |
if (sharedptr) { ... } |
|
604 |
\endcode |
|
605 |
||
606 |
\sa isNull() |
|
607 |
*/ |
|
608 |
||
609 |
/*! |
|
610 |
\fn bool QSharedPointer::operator !() const |
|
611 |
||
612 |
Returns true if this object is null. This function is suitable |
|
613 |
for use in \tt if-constructs, like: |
|
614 |
||
615 |
\code |
|
616 |
if (!sharedptr) { ... } |
|
617 |
\endcode |
|
618 |
||
619 |
\sa isNull() |
|
620 |
*/ |
|
621 |
||
622 |
/*! |
|
623 |
\fn QSharedPointer<X> QSharedPointer::staticCast() const |
|
624 |
||
625 |
Performs a static cast from this pointer's type to \tt X and returns |
|
626 |
a QSharedPointer that shares the reference. This function can be |
|
627 |
used for up- and for down-casting, but is more useful for |
|
628 |
up-casting. |
|
629 |
||
630 |
Note: the template type \c X must have the same const and volatile |
|
631 |
qualifiers as the template of this object, or the cast will |
|
632 |
fail. Use constCast() if you need to drop those qualifiers. |
|
633 |
||
634 |
\sa dynamicCast(), constCast(), qSharedPointerCast() |
|
635 |
*/ |
|
636 |
||
637 |
/*! |
|
638 |
\fn QSharedPointer<X> QSharedPointer::dynamicCast() const |
|
639 |
||
640 |
Performs a dynamic cast from this pointer's type to \tt X and |
|
641 |
returns a QSharedPointer that shares the reference. If this |
|
642 |
function is used to up-cast, then QSharedPointer will perform a \tt |
|
643 |
dynamic_cast, which means that if the object being pointed by this |
|
644 |
QSharedPointer is not of type \tt X, the returned object will be |
|
645 |
null. |
|
646 |
||
647 |
Note: the template type \c X must have the same const and volatile |
|
648 |
qualifiers as the template of this object, or the cast will |
|
649 |
fail. Use constCast() if you need to drop those qualifiers. |
|
650 |
||
651 |
\sa qSharedPointerDynamicCast() |
|
652 |
*/ |
|
653 |
||
654 |
/*! |
|
655 |
\fn QSharedPointer<X> QSharedPointer::constCast() const |
|
656 |
||
657 |
Performs a \tt const_cast from this pointer's type to \tt X and returns |
|
658 |
a QSharedPointer that shares the reference. This function can be |
|
659 |
used for up- and for down-casting, but is more useful for |
|
660 |
up-casting. |
|
661 |
||
662 |
\sa isNull(), qSharedPointerConstCast() |
|
663 |
*/ |
|
664 |
||
665 |
/*! |
|
666 |
\fn QSharedPointer<X> QSharedPointer::objectCast() const |
|
667 |
\since 4.6 |
|
668 |
||
669 |
Performs a \l qobject_cast() from this pointer's type to \tt X and |
|
670 |
returns a QSharedPointer that shares the reference. If this |
|
671 |
function is used to up-cast, then QSharedPointer will perform a \tt |
|
672 |
qobject_cast, which means that if the object being pointed by this |
|
673 |
QSharedPointer is not of type \tt X, the returned object will be |
|
674 |
null. |
|
675 |
||
676 |
Note: the template type \c X must have the same const and volatile |
|
677 |
qualifiers as the template of this object, or the cast will |
|
678 |
fail. Use constCast() if you need to drop those qualifiers. |
|
679 |
||
680 |
\sa qSharedPointerObjectCast() |
|
681 |
*/ |
|
682 |
||
683 |
/*! |
|
684 |
\fn QWeakPointer<T> QSharedPointer::toWeakRef() const |
|
685 |
||
686 |
Returns a weak reference object that shares the pointer referenced |
|
687 |
by this object. |
|
688 |
||
689 |
\sa QWeakPointer::QWeakPointer() |
|
690 |
*/ |
|
691 |
||
692 |
/*! |
|
693 |
\fn void QSharedPointer::clear() |
|
694 |
||
695 |
Clears this QSharedPointer object, dropping the reference that it |
|
696 |
may have had to the pointer. If this was the last reference, then |
|
697 |
the pointer itself will be deleted. |
|
698 |
*/ |
|
699 |
||
700 |
/*! |
|
701 |
\fn QWeakPointer::QWeakPointer() |
|
702 |
||
703 |
Creates a QWeakPointer that points to nothing. |
|
704 |
*/ |
|
705 |
||
706 |
/*! |
|
707 |
\fn QWeakPointer::~QWeakPointer() |
|
708 |
||
709 |
Destroys this QWeakPointer object. The pointer referenced |
|
710 |
by this object will not be deleted. |
|
711 |
*/ |
|
712 |
||
713 |
/*! |
|
714 |
\fn QWeakPointer::QWeakPointer(const QWeakPointer<T> &other) |
|
715 |
||
716 |
Creates a QWeakPointer that holds a weak reference to the |
|
717 |
pointer referenced by \a other. |
|
718 |
||
719 |
If \tt T is a derived type of the template parameter of this |
|
720 |
class, QWeakPointer will perform an automatic cast. Otherwise, |
|
721 |
you will get a compiler error. |
|
722 |
*/ |
|
723 |
||
724 |
/*! |
|
725 |
\fn QWeakPointer::QWeakPointer(const QSharedPointer<T> &other) |
|
726 |
||
727 |
Creates a QWeakPointer that holds a weak reference to the |
|
728 |
pointer referenced by \a other. |
|
729 |
||
730 |
If \tt T is a derived type of the template parameter of this |
|
731 |
class, QWeakPointer will perform an automatic cast. Otherwise, |
|
732 |
you will get a compiler error. |
|
733 |
*/ |
|
734 |
||
735 |
/*! |
|
736 |
\fn QWeakPointer::QWeakPointer(const QObject *obj) |
|
737 |
\since 4.6 |
|
738 |
||
739 |
Creates a QWeakPointer that holds a weak reference directly to the |
|
740 |
QObject \a obj. This constructor is only available if the template type |
|
741 |
\tt T is QObject or derives from it (otherwise a compilation error will |
|
742 |
result). |
|
743 |
||
744 |
You can use this constructor with any QObject, even if they were not |
|
745 |
created with \l QSharedPointer. |
|
746 |
||
747 |
Note that QWeakPointers created this way on arbitrary QObjects usually |
|
748 |
cannot be promoted to QSharedPointer. |
|
749 |
||
750 |
\sa QSharedPointer, QWeakPointer#tracking-qobject |
|
751 |
*/ |
|
752 |
||
753 |
/*! |
|
754 |
\fn QWeakPointer &QWeakPointer::operator=(const QObject *obj) |
|
755 |
\since 4.6 |
|
756 |
||
757 |
Makes this QWeakPointer hold a weak reference to directly to the QObject |
|
758 |
\a obj. This function is only available if the template type \tt T is |
|
759 |
QObject or derives from it. |
|
760 |
||
761 |
\sa QWeakPointer#tracking-qobject |
|
762 |
*/ |
|
763 |
||
764 |
/*! |
|
765 |
\fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other) |
|
766 |
||
767 |
Makes this object share \a other's pointer. The current pointer |
|
768 |
reference is discarded but is not deleted. |
|
769 |
||
770 |
If \tt T is a derived type of the template parameter of this |
|
771 |
class, QWeakPointer will perform an automatic cast. Otherwise, |
|
772 |
you will get a compiler error. |
|
773 |
*/ |
|
774 |
||
775 |
/*! |
|
776 |
\fn QWeakPointer &QWeakPointer::operator=(const QSharedPointer<T> &other) |
|
777 |
||
778 |
Makes this object share \a other's pointer. The current pointer |
|
779 |
reference is discarded but is not deleted. |
|
780 |
||
781 |
If \tt T is a derived type of the template parameter of this |
|
782 |
class, QWeakPointer will perform an automatic cast. Otherwise, |
|
783 |
you will get a compiler error. |
|
784 |
*/ |
|
785 |
||
786 |
/*! |
|
787 |
\fn bool QWeakPointer::isNull() const |
|
788 |
||
789 |
Returns true if this object is holding a reference to a null |
|
790 |
pointer. |
|
791 |
||
792 |
Note that, due to the nature of weak references, the pointer that |
|
793 |
QWeakPointer references can become null at any moment, so |
|
794 |
the value returned from this function can change from false to |
|
795 |
true from one call to the next. |
|
796 |
*/ |
|
797 |
||
798 |
/*! |
|
799 |
\fn QWeakPointer::operator bool() const |
|
800 |
||
801 |
Returns true if this object is not null. This function is suitable |
|
802 |
for use in \tt if-constructs, like: |
|
803 |
||
804 |
\code |
|
805 |
if (weakref) { ... } |
|
806 |
\endcode |
|
807 |
||
808 |
Note that, due to the nature of weak references, the pointer that |
|
809 |
QWeakPointer references can become null at any moment, so |
|
810 |
the value returned from this function can change from true to |
|
811 |
false from one call to the next. |
|
812 |
||
813 |
\sa isNull() |
|
814 |
*/ |
|
815 |
||
816 |
/*! |
|
817 |
\fn bool QWeakPointer::operator !() const |
|
818 |
||
819 |
Returns true if this object is null. This function is suitable |
|
820 |
for use in \tt if-constructs, like: |
|
821 |
||
822 |
\code |
|
823 |
if (!weakref) { ... } |
|
824 |
\endcode |
|
825 |
||
826 |
Note that, due to the nature of weak references, the pointer that |
|
827 |
QWeakPointer references can become null at any moment, so |
|
828 |
the value returned from this function can change from false to |
|
829 |
true from one call to the next. |
|
830 |
||
831 |
\sa isNull() |
|
832 |
*/ |
|
833 |
||
834 |
/*! |
|
835 |
\fn T *QWeakPointer::data() const |
|
836 |
\since 4.6 |
|
837 |
||
838 |
Returns the value of the pointer being tracked by this QWeakPointer, |
|
839 |
\b without ensuring that it cannot get deleted. To have that guarantee, |
|
840 |
use toStrongRef(), which returns a QSharedPointer object. If this |
|
841 |
function can determine that the pointer has already been deleted, it |
|
842 |
returns 0. |
|
843 |
||
844 |
It is ok to obtain the value of the pointer and using that value itself, |
|
845 |
like for example in debugging statements: |
|
846 |
||
847 |
\code |
|
848 |
qDebug("Tracking %p", weakref.data()); |
|
849 |
\endcode |
|
850 |
||
851 |
However, dereferencing the pointer is only allowed if you can guarantee |
|
852 |
by external means that the pointer does not get deleted. For example, |
|
853 |
if you can be certain that no other thread can delete it, nor the |
|
854 |
functions that you may call. |
|
855 |
||
856 |
If that is the case, then the following code is valid: |
|
857 |
||
858 |
\code |
|
859 |
// this pointer cannot be used in another thread |
|
860 |
// so other threads cannot delete it |
|
861 |
QWeakPointer<int> weakref = obtainReference(); |
|
862 |
||
863 |
Object *obj = weakref.data(); |
|
864 |
if (obj) { |
|
865 |
// if the pointer wasn't deleted yet, we know it can't get |
|
866 |
// deleted by our own code here nor the functions we call |
|
867 |
otherFunction(obj); |
|
868 |
} |
|
869 |
\endcode |
|
870 |
||
871 |
Use this function with care. |
|
872 |
||
873 |
\sa isNull(), toStrongRef() |
|
874 |
*/ |
|
875 |
||
876 |
/*! |
|
877 |
\fn QSharedPointer<T> QWeakPointer::toStrongRef() const |
|
878 |
||
879 |
Promotes this weak reference to a strong one and returns a |
|
880 |
QSharedPointer object holding that reference. When promoting to |
|
881 |
QSharedPointer, this function verifies if the object has been deleted |
|
882 |
already or not. If it hasn't, this function increases the reference |
|
883 |
count to the shared object, thus ensuring that it will not get |
|
884 |
deleted. |
|
885 |
||
886 |
Since this function can fail to obtain a valid strong reference to the |
|
887 |
shared object, you should always verify if the conversion succeeded, |
|
888 |
by calling QSharedPointer::isNull() on the returned object. |
|
889 |
||
890 |
For example, the following code promotes a QWeakPointer that was held |
|
891 |
to a strong reference and, if it succeeded, it prints the value of the |
|
892 |
integer that was held: |
|
893 |
||
894 |
\code |
|
895 |
QWeakPointer<int> weakref; |
|
896 |
||
897 |
// ... |
|
898 |
||
899 |
QSharedPointer<int> strong = weakref.toStrongRef(); |
|
900 |
if (strong) |
|
901 |
qDebug() << "The value is:" << *strong; |
|
902 |
else |
|
903 |
qDebug() << "The value has already been deleted"; |
|
904 |
\endcode |
|
905 |
||
906 |
\sa QSharedPointer::QSharedPointer() |
|
907 |
*/ |
|
908 |
||
909 |
/*! |
|
910 |
\fn void QWeakPointer::clear() |
|
911 |
||
912 |
Clears this QWeakPointer object, dropping the reference that it |
|
913 |
may have had to the pointer. |
|
914 |
*/ |
|
915 |
||
916 |
/*! |
|
917 |
\fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) |
|
918 |
\relates QSharedPointer |
|
919 |
||
920 |
Returns true if the pointer referenced by \a ptr1 is the |
|
921 |
same pointer as that referenced by \a ptr2. |
|
922 |
||
923 |
If \a ptr2's template parameter is different from \a ptr1's, |
|
924 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
925 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
926 |
template parameter is not a base or a derived type from |
|
927 |
\a ptr1's, you will get a compiler error. |
|
928 |
*/ |
|
929 |
||
930 |
/*! |
|
931 |
\fn bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) |
|
932 |
\relates QSharedPointer |
|
933 |
||
934 |
Returns true if the pointer referenced by \a ptr1 is not the |
|
935 |
same pointer as that referenced by \a ptr2. |
|
936 |
||
937 |
If \a ptr2's template parameter is different from \a ptr1's, |
|
938 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
939 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
940 |
template parameter is not a base or a derived type from |
|
941 |
\a ptr1's, you will get a compiler error. |
|
942 |
*/ |
|
943 |
||
944 |
/*! |
|
945 |
\fn bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) |
|
946 |
\relates QSharedPointer |
|
947 |
||
948 |
Returns true if the pointer referenced by \a ptr1 is the |
|
949 |
same pointer as \a ptr2. |
|
950 |
||
951 |
If \a ptr2's type is different from \a ptr1's, |
|
952 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
953 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
954 |
type is not a base or a derived type from this |
|
955 |
\a ptr1's, you will get a compiler error. |
|
956 |
*/ |
|
957 |
||
958 |
/*! |
|
959 |
\fn bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) |
|
960 |
\relates QSharedPointer |
|
961 |
||
962 |
Returns true if the pointer referenced by \a ptr1 is not the |
|
963 |
same pointer as \a ptr2. |
|
964 |
||
965 |
If \a ptr2's type is different from \a ptr1's, |
|
966 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
967 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
968 |
type is not a base or a derived type from this |
|
969 |
\a ptr1's, you will get a compiler error. |
|
970 |
*/ |
|
971 |
||
972 |
/*! |
|
973 |
\fn bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) |
|
974 |
\relates QSharedPointer |
|
975 |
||
976 |
Returns true if the pointer \a ptr1 is the |
|
977 |
same pointer as that referenced by \a ptr2. |
|
978 |
||
979 |
If \a ptr2's template parameter is different from \a ptr1's type, |
|
980 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
981 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
982 |
template parameter is not a base or a derived type from |
|
983 |
\a ptr1's type, you will get a compiler error. |
|
984 |
*/ |
|
985 |
||
986 |
/*! |
|
987 |
\fn bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) |
|
988 |
\relates QSharedPointer |
|
989 |
||
990 |
Returns true if the pointer \a ptr1 is not the |
|
991 |
same pointer as that referenced by \a ptr2. |
|
992 |
||
993 |
If \a ptr2's template parameter is different from \a ptr1's type, |
|
994 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
995 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
996 |
template parameter is not a base or a derived type from |
|
997 |
\a ptr1's type, you will get a compiler error. |
|
998 |
*/ |
|
999 |
||
1000 |
/*! |
|
1001 |
\fn bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) |
|
1002 |
\relates QWeakPointer |
|
1003 |
||
1004 |
Returns true if the pointer referenced by \a ptr1 is the |
|
1005 |
same pointer as that referenced by \a ptr2. |
|
1006 |
||
1007 |
If \a ptr2's template parameter is different from \a ptr1's, |
|
1008 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
1009 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
1010 |
template parameter is not a base or a derived type from |
|
1011 |
\a ptr1's, you will get a compiler error. |
|
1012 |
*/ |
|
1013 |
||
1014 |
/*! |
|
1015 |
\fn bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) |
|
1016 |
\relates QWeakPointer |
|
1017 |
||
1018 |
Returns true if the pointer referenced by \a ptr1 is not the |
|
1019 |
same pointer as that referenced by \a ptr2. |
|
1020 |
||
1021 |
If \a ptr2's template parameter is different from \a ptr1's, |
|
1022 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
1023 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
1024 |
template parameter is not a base or a derived type from |
|
1025 |
\a ptr1's, you will get a compiler error. |
|
1026 |
*/ |
|
1027 |
||
1028 |
/*! |
|
1029 |
\fn bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2) |
|
1030 |
\relates QWeakPointer |
|
1031 |
||
1032 |
Returns true if the pointer referenced by \a ptr1 is the |
|
1033 |
same pointer as that referenced by \a ptr2. |
|
1034 |
||
1035 |
If \a ptr2's template parameter is different from \a ptr1's, |
|
1036 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
1037 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
1038 |
template parameter is not a base or a derived type from |
|
1039 |
\a ptr1's, you will get a compiler error. |
|
1040 |
*/ |
|
1041 |
||
1042 |
/*! |
|
1043 |
\fn bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2) |
|
1044 |
\relates QWeakPointer |
|
1045 |
||
1046 |
Returns true if the pointer referenced by \a ptr1 is not the |
|
1047 |
same pointer as that referenced by \a ptr2. |
|
1048 |
||
1049 |
If \a ptr2's template parameter is different from \a ptr1's, |
|
1050 |
QSharedPointer will attempt to perform an automatic \tt static_cast |
|
1051 |
to ensure that the pointers being compared are equal. If \a ptr2's |
|
1052 |
template parameter is not a base or a derived type from |
|
1053 |
\a ptr1's, you will get a compiler error. |
|
1054 |
*/ |
|
1055 |
||
1056 |
/*! |
|
1057 |
\fn QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other) |
|
1058 |
\relates QSharedPointer |
|
1059 |
||
1060 |
Returns a shared pointer to the pointer held by \a other, cast to |
|
1061 |
type \tt X. The types \tt T and \tt X must belong to one |
|
1062 |
hierarchy for the \tt static_cast to succeed. |
|
1063 |
||
1064 |
Note that \tt X must have the same cv-qualifiers (\tt const and |
|
1065 |
\tt volatile) that \tt T has, or the code will fail to |
|
1066 |
compile. Use qSharedPointerConstCast to cast away the constness. |
|
1067 |
||
1068 |
\sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast() |
|
1069 |
*/ |
|
1070 |
||
1071 |
/*! |
|
1072 |
\fn QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other) |
|
1073 |
\relates QSharedPointer |
|
1074 |
\relates QWeakPointer |
|
1075 |
||
1076 |
Returns a shared pointer to the pointer held by \a other, cast to |
|
1077 |
type \tt X. The types \tt T and \tt X must belong to one |
|
1078 |
hierarchy for the \tt static_cast to succeed. |
|
1079 |
||
1080 |
The \a other object is converted first to a strong reference. If |
|
1081 |
that conversion fails (because the object it's pointing to has |
|
1082 |
already been deleted), this function returns a null |
|
1083 |
QSharedPointer. |
|
1084 |
||
1085 |
Note that \tt X must have the same cv-qualifiers (\tt const and |
|
1086 |
\tt volatile) that \tt T has, or the code will fail to |
|
1087 |
compile. Use qSharedPointerConstCast to cast away the constness. |
|
1088 |
||
1089 |
\sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast() |
|
1090 |
*/ |
|
1091 |
||
1092 |
/*! |
|
1093 |
\fn QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &other) |
|
1094 |
\relates QSharedPointer |
|
1095 |
||
1096 |
Returns a shared pointer to the pointer held by \a other, using a |
|
1097 |
dynamic cast to type \tt X to obtain an internal pointer of the |
|
1098 |
appropriate type. If the \tt dynamic_cast fails, the object |
|
1099 |
returned will be null. |
|
1100 |
||
1101 |
Note that \tt X must have the same cv-qualifiers (\tt const and |
|
1102 |
\tt volatile) that \tt T has, or the code will fail to |
|
1103 |
compile. Use qSharedPointerConstCast to cast away the constness. |
|
1104 |
||
1105 |
\sa QSharedPointer::dynamicCast(), qSharedPointerCast(), qSharedPointerConstCast() |
|
1106 |
*/ |
|
1107 |
||
1108 |
/*! |
|
1109 |
\fn QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &other) |
|
1110 |
\relates QSharedPointer |
|
1111 |
\relates QWeakPointer |
|
1112 |
||
1113 |
Returns a shared pointer to the pointer held by \a other, using a |
|
1114 |
dynamic cast to type \tt X to obtain an internal pointer of the |
|
1115 |
appropriate type. If the \tt dynamic_cast fails, the object |
|
1116 |
returned will be null. |
|
1117 |
||
1118 |
The \a other object is converted first to a strong reference. If |
|
1119 |
that conversion fails (because the object it's pointing to has |
|
1120 |
already been deleted), this function also returns a null |
|
1121 |
QSharedPointer. |
|
1122 |
||
1123 |
Note that \tt X must have the same cv-qualifiers (\tt const and |
|
1124 |
\tt volatile) that \tt T has, or the code will fail to |
|
1125 |
compile. Use qSharedPointerConstCast to cast away the constness. |
|
1126 |
||
1127 |
\sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast() |
|
1128 |
*/ |
|
1129 |
||
1130 |
/*! |
|
1131 |
\fn QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &other) |
|
1132 |
\relates QSharedPointer |
|
1133 |
||
1134 |
Returns a shared pointer to the pointer held by \a other, cast to |
|
1135 |
type \tt X. The types \tt T and \tt X must belong to one |
|
1136 |
hierarchy for the \tt const_cast to succeed. The \tt const and \tt |
|
1137 |
volatile differences between \tt T and \tt X are ignored. |
|
1138 |
||
1139 |
\sa QSharedPointer::constCast(), qSharedPointerCast(), qSharedPointerDynamicCast() |
|
1140 |
*/ |
|
1141 |
||
1142 |
/*! |
|
1143 |
\fn QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &other) |
|
1144 |
\relates QSharedPointer |
|
1145 |
\relates QWeakPointer |
|
1146 |
||
1147 |
Returns a shared pointer to the pointer held by \a other, cast to |
|
1148 |
type \tt X. The types \tt T and \tt X must belong to one |
|
1149 |
hierarchy for the \tt const_cast to succeed. The \tt const and |
|
1150 |
\tt volatile differences between \tt T and \tt X are ignored. |
|
1151 |
||
1152 |
The \a other object is converted first to a strong reference. If |
|
1153 |
that conversion fails (because the object it's pointing to has |
|
1154 |
already been deleted), this function returns a null |
|
1155 |
QSharedPointer. |
|
1156 |
||
1157 |
\sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerDynamicCast() |
|
1158 |
*/ |
|
1159 |
||
1160 |
/*! |
|
1161 |
\fn QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &other) |
|
1162 |
\relates QSharedPointer |
|
1163 |
\since 4.6 |
|
1164 |
||
1165 |
\brief The qSharedPointerObjectCast function is for casting a shared pointer. |
|
1166 |
||
1167 |
Returns a shared pointer to the pointer held by \a other, using a |
|
1168 |
\l qobject_cast() to type \tt X to obtain an internal pointer of the |
|
1169 |
appropriate type. If the \tt qobject_cast fails, the object |
|
1170 |
returned will be null. |
|
1171 |
||
1172 |
Note that \tt X must have the same cv-qualifiers (\tt const and |
|
1173 |
\tt volatile) that \tt T has, or the code will fail to |
|
1174 |
compile. Use qSharedPointerConstCast to cast away the constness. |
|
1175 |
||
1176 |
\sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast() |
|
1177 |
*/ |
|
1178 |
||
1179 |
/*! |
|
1180 |
\fn QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &other) |
|
1181 |
\relates QSharedPointer |
|
1182 |
\relates QWeakPointer |
|
1183 |
\since 4.6 |
|
1184 |
||
1185 |
\brief The qSharedPointerObjectCast function is for casting a shared pointer. |
|
1186 |
||
1187 |
Returns a shared pointer to the pointer held by \a other, using a |
|
1188 |
\l qobject_cast() to type \tt X to obtain an internal pointer of the |
|
1189 |
appropriate type. If the \tt qobject_cast fails, the object |
|
1190 |
returned will be null. |
|
1191 |
||
1192 |
The \a other object is converted first to a strong reference. If |
|
1193 |
that conversion fails (because the object it's pointing to has |
|
1194 |
already been deleted), this function also returns a null |
|
1195 |
QSharedPointer. |
|
1196 |
||
1197 |
Note that \tt X must have the same cv-qualifiers (\tt const and |
|
1198 |
\tt volatile) that \tt T has, or the code will fail to |
|
1199 |
compile. Use qSharedPointerConstCast to cast away the constness. |
|
1200 |
||
1201 |
\sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast() |
|
1202 |
*/ |
|
1203 |
||
1204 |
||
1205 |
/*! |
|
1206 |
\fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other) |
|
1207 |
\relates QWeakPointer |
|
1208 |
||
1209 |
Returns a weak pointer to the pointer held by \a other, cast to |
|
1210 |
type \tt X. The types \tt T and \tt X must belong to one |
|
1211 |
hierarchy for the \tt static_cast to succeed. |
|
1212 |
||
1213 |
Note that \tt X must have the same cv-qualifiers (\tt const and |
|
1214 |
\tt volatile) that \tt T has, or the code will fail to |
|
1215 |
compile. Use qSharedPointerConstCast to cast away the constness. |
|
1216 |
*/ |
|
1217 |
||
1218 |
#include <qset.h> |
|
1219 |
#include <qmutex.h> |
|
1220 |
||
1221 |
#if !defined(QT_NO_QOBJECT) |
|
1222 |
#include "private/qobject_p.h" |
|
1223 |
||
1224 |
QT_BEGIN_NAMESPACE |
|
1225 |
||
1226 |
/*! |
|
1227 |
\internal |
|
1228 |
This function is called for a just-created QObject \a obj, to enable |
|
1229 |
the use of QSharedPointer and QWeakPointer. |
|
1230 |
||
1231 |
When QSharedPointer is active in a QObject, the object must not be deleted |
|
1232 |
directly: the lifetime is managed by the QSharedPointer object. In that case, |
|
1233 |
the deleteLater() and parent-child relationship in QObject only decrease |
|
1234 |
the strong reference count, instead of deleting the object. |
|
1235 |
*/ |
|
1236 |
void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *obj, bool) |
|
1237 |
{ |
|
1238 |
Q_ASSERT(obj); |
|
1239 |
QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); |
|
1240 |
||
1241 |
if (d->sharedRefcount) |
|
1242 |
qFatal("QSharedPointer: pointer %p already has reference counting", obj); |
|
1243 |
d->sharedRefcount = this; |
|
1244 |
||
1245 |
// QObject decreases the refcount too, so increase it up |
|
1246 |
weakref.ref(); |
|
1247 |
} |
|
1248 |
||
1249 |
QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj) |
|
1250 |
{ |
|
1251 |
Q_ASSERT(obj); |
|
1252 |
QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); |
|
1253 |
Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted"); |
|
1254 |
||
1255 |
ExternalRefCountData *that = d->sharedRefcount; |
|
1256 |
if (that) { |
|
1257 |
that->weakref.ref(); |
|
1258 |
return that; |
|
1259 |
} |
|
1260 |
||
1261 |
// we can create the refcount data because it doesn't exist |
|
1262 |
ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized); |
|
1263 |
x->strongref = -1; |
|
1264 |
x->weakref = 2; // the QWeakPointer that called us plus the QObject itself |
|
1265 |
if (!d->sharedRefcount.testAndSetRelease(0, x)) { |
|
1266 |
delete x; |
|
1267 |
d->sharedRefcount->weakref.ref(); |
|
1268 |
} |
|
1269 |
return d->sharedRefcount; |
|
1270 |
} |
|
1271 |
||
1272 |
QT_END_NAMESPACE |
|
1273 |
||
1274 |
#endif |
|
1275 |
||
1276 |
||
1277 |
||
1278 |
#if !defined(QT_NO_MEMBER_TEMPLATES) |
|
1279 |
||
1280 |
//# define QT_SHARED_POINTER_BACKTRACE_SUPPORT |
|
1281 |
# ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT |
|
1282 |
# if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE) |
|
1283 |
# define BACKTRACE_SUPPORTED |
|
1284 |
# elif defined(Q_OS_MACX) |
|
1285 |
# define BACKTRACE_SUPPORTED |
|
1286 |
# endif |
|
1287 |
# endif |
|
1288 |
||
1289 |
# if defined(BACKTRACE_SUPPORTED) |
|
1290 |
# include <sys/types.h> |
|
1291 |
# include <execinfo.h> |
|
1292 |
# include <stdio.h> |
|
1293 |
# include <unistd.h> |
|
1294 |
# include <sys/wait.h> |
|
1295 |
||
1296 |
QT_BEGIN_NAMESPACE |
|
1297 |
||
1298 |
static inline QByteArray saveBacktrace() __attribute__((always_inline)); |
|
1299 |
static inline QByteArray saveBacktrace() |
|
1300 |
{ |
|
1301 |
static const int maxFrames = 32; |
|
1302 |
||
1303 |
QByteArray stacktrace; |
|
1304 |
stacktrace.resize(sizeof(void*) * maxFrames); |
|
1305 |
int stack_size = backtrace((void**)stacktrace.data(), maxFrames); |
|
1306 |
stacktrace.resize(sizeof(void*) * stack_size); |
|
1307 |
||
1308 |
return stacktrace; |
|
1309 |
} |
|
1310 |
||
1311 |
static void printBacktrace(QByteArray stacktrace) |
|
1312 |
{ |
|
1313 |
void *const *stack = (void *const *)stacktrace.constData(); |
|
1314 |
int stack_size = stacktrace.size() / sizeof(void*); |
|
1315 |
char **stack_symbols = backtrace_symbols(stack, stack_size); |
|
1316 |
||
1317 |
int filter[2]; |
|
1318 |
pid_t child = -1; |
|
1319 |
if (pipe(filter) != -1) |
|
1320 |
child = fork(); |
|
1321 |
if (child == 0) { |
|
1322 |
// child process |
|
1323 |
dup2(fileno(stderr), fileno(stdout)); |
|
1324 |
dup2(filter[0], fileno(stdin)); |
|
1325 |
close(filter[0]); |
|
1326 |
close(filter[1]); |
|
1327 |
execlp("c++filt", "c++filt", "-n", NULL); |
|
1328 |
||
1329 |
// execlp failed |
|
1330 |
execl("/bin/cat", "/bin/cat", NULL); |
|
1331 |
_exit(127); |
|
1332 |
} |
|
1333 |
||
1334 |
// parent process |
|
1335 |
close(filter[0]); |
|
1336 |
FILE *output; |
|
1337 |
if (child == -1) { |
|
1338 |
// failed forking |
|
1339 |
close(filter[1]); |
|
1340 |
output = stderr; |
|
1341 |
} else { |
|
1342 |
output = fdopen(filter[1], "w"); |
|
1343 |
} |
|
1344 |
||
1345 |
fprintf(stderr, "Backtrace of the first creation (most recent frame first):\n"); |
|
1346 |
for (int i = 0; i < stack_size; ++i) { |
|
1347 |
if (strlen(stack_symbols[i])) |
|
1348 |
fprintf(output, "#%-2d %s\n", i, stack_symbols[i]); |
|
1349 |
else |
|
1350 |
fprintf(output, "#%-2d %p\n", i, stack[i]); |
|
1351 |
} |
|
1352 |
||
1353 |
if (child != -1) { |
|
1354 |
fclose(output); |
|
1355 |
waitpid(child, 0, 0); |
|
1356 |
} |
|
1357 |
} |
|
1358 |
||
1359 |
QT_END_NAMESPACE |
|
1360 |
||
1361 |
# endif // BACKTRACE_SUPPORTED |
|
1362 |
||
1363 |
namespace { |
|
1364 |
QT_USE_NAMESPACE |
|
1365 |
struct Data { |
|
1366 |
const volatile void *pointer; |
|
1367 |
# ifdef BACKTRACE_SUPPORTED |
|
1368 |
QByteArray backtrace; |
|
1369 |
# endif |
|
1370 |
}; |
|
1371 |
||
1372 |
class KnownPointers |
|
1373 |
{ |
|
1374 |
public: |
|
1375 |
QMutex mutex; |
|
1376 |
QHash<const void *, Data> dPointers; |
|
1377 |
QHash<const volatile void *, const void *> dataPointers; |
|
1378 |
}; |
|
1379 |
} |
|
1380 |
||
1381 |
Q_GLOBAL_STATIC(KnownPointers, knownPointers) |
|
1382 |
||
1383 |
QT_BEGIN_NAMESPACE |
|
1384 |
||
1385 |
namespace QtSharedPointer { |
|
1386 |
Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); |
|
1387 |
Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); |
|
1388 |
Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck(); |
|
1389 |
} |
|
1390 |
||
1391 |
/*! |
|
1392 |
\internal |
|
1393 |
*/ |
|
1394 |
void QtSharedPointer::internalSafetyCheckAdd(const volatile void *) |
|
1395 |
{ |
|
1396 |
// Qt 4.5 compatibility |
|
1397 |
// this function is broken by design, so it was replaced with internalSafetyCheckAdd2 |
|
1398 |
// |
|
1399 |
// it's broken because we tracked the pointers added and |
|
1400 |
// removed from QSharedPointer, converted to void*. |
|
1401 |
// That is, this is supposed to track the "top-of-object" pointer in |
|
1402 |
// case of multiple inheritance. |
|
1403 |
// |
|
1404 |
// However, it doesn't work well in some compilers: |
|
1405 |
// if you create an object with a class of type A and the last reference |
|
1406 |
// is dropped of type B, then the value passed to internalSafetyCheckRemove could |
|
1407 |
// be different than was added. That would leave dangling addresses. |
|
1408 |
// |
|
1409 |
// So instead, we track the pointer by the d-pointer instead. |
|
1410 |
} |
|
1411 |
||
1412 |
/*! |
|
1413 |
\internal |
|
1414 |
*/ |
|
1415 |
void QtSharedPointer::internalSafetyCheckRemove(const volatile void *) |
|
1416 |
{ |
|
1417 |
// Qt 4.5 compatibility |
|
1418 |
// see comments above |
|
1419 |
} |
|
1420 |
||
1421 |
/*! |
|
1422 |
\internal |
|
1423 |
*/ |
|
1424 |
void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile void *ptr) |
|
1425 |
{ |
|
1426 |
// see comments above for the rationale for this function |
|
1427 |
KnownPointers *const kp = knownPointers(); |
|
1428 |
if (!kp) |
|
1429 |
return; // end-game: the application is being destroyed already |
|
1430 |
||
1431 |
QMutexLocker lock(&kp->mutex); |
|
1432 |
Q_ASSERT(!kp->dPointers.contains(d_ptr)); |
|
1433 |
||
1434 |
//qDebug("Adding d=%p value=%p", d_ptr, ptr); |
|
1435 |
||
1436 |
const void *other_d_ptr = kp->dataPointers.value(ptr, 0); |
|
1437 |
if (other_d_ptr) { |
|
1438 |
# ifdef BACKTRACE_SUPPORTED |
|
1439 |
printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace); |
|
1440 |
# endif |
|
1441 |
qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked " |
|
1442 |
"by another QSharedPointer object %p", ptr, other_d_ptr); |
|
1443 |
} |
|
1444 |
||
1445 |
Data data; |
|
1446 |
data.pointer = ptr; |
|
1447 |
# ifdef BACKTRACE_SUPPORTED |
|
1448 |
data.backtrace = saveBacktrace(); |
|
1449 |
# endif |
|
1450 |
||
1451 |
kp->dPointers.insert(d_ptr, data); |
|
1452 |
kp->dataPointers.insert(ptr, d_ptr); |
|
1453 |
Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); |
|
1454 |
} |
|
1455 |
||
1456 |
/*! |
|
1457 |
\internal |
|
1458 |
*/ |
|
1459 |
void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr) |
|
1460 |
{ |
|
1461 |
KnownPointers *const kp = knownPointers(); |
|
1462 |
if (!kp) |
|
1463 |
return; // end-game: the application is being destroyed already |
|
1464 |
||
1465 |
QMutexLocker lock(&kp->mutex); |
|
1466 |
||
1467 |
QHash<const void *, Data>::iterator it = kp->dPointers.find(d_ptr); |
|
1468 |
if (it == kp->dPointers.end()) { |
|
1469 |
qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. " |
|
1470 |
"To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout " |
|
1471 |
"in your code.", d_ptr); |
|
1472 |
} |
|
1473 |
||
1474 |
QHash<const volatile void *, const void *>::iterator it2 = kp->dataPointers.find(it->pointer); |
|
1475 |
Q_ASSERT(it2 != kp->dataPointers.end()); |
|
1476 |
||
1477 |
//qDebug("Removing d=%p value=%p", d_ptr, it->pointer); |
|
1478 |
||
1479 |
// remove entries |
|
1480 |
kp->dataPointers.erase(it2); |
|
1481 |
kp->dPointers.erase(it); |
|
1482 |
Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); |
|
1483 |
} |
|
1484 |
||
1485 |
/*! |
|
1486 |
\internal |
|
1487 |
Called by the QSharedPointer autotest |
|
1488 |
*/ |
|
1489 |
void QtSharedPointer::internalSafetyCheckCleanCheck() |
|
1490 |
{ |
|
1491 |
# ifdef QT_BUILD_INTERNAL |
|
1492 |
KnownPointers *const kp = knownPointers(); |
|
1493 |
Q_ASSERT_X(kp, "internalSafetyCheckSelfCheck()", "Called after global statics deletion!"); |
|
1494 |
||
1495 |
if (kp->dPointers.size() != kp->dataPointers.size()) |
|
1496 |
qFatal("Internal consistency error: the number of pointers is not equal!"); |
|
1497 |
||
1498 |
if (!kp->dPointers.isEmpty()) |
|
1499 |
qFatal("Pointer cleaning failed: %d entries remaining", kp->dPointers.size()); |
|
1500 |
# endif |
|
1501 |
} |
|
1502 |
||
1503 |
QT_END_NAMESPACE |
|
1504 |
||
1505 |
#endif |