1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation ([email protected])
|
---|
6 | **
|
---|
7 | ** This file is part of the QtCore module of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
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 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "qsharedpointer.h"
|
---|
43 |
|
---|
44 | // to be sure we aren't causing a namespace clash:
|
---|
45 | #include "qshareddata.h"
|
---|
46 |
|
---|
47 | /*!
|
---|
48 | \class QSharedPointer
|
---|
49 | \brief The QSharedPointer class holds a strong reference to a shared pointer
|
---|
50 | \since 4.5
|
---|
51 |
|
---|
52 | \reentrant
|
---|
53 |
|
---|
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
|
---|