0
|
1 |
/****************************************************************************
|
|
2 |
**
|
|
3 |
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
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,
|
|
133 |
QSharedPointer's pointer tracking mechanism mail fail to detect that the
|
|
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
|