Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 556256 Details for
Bug 671882
x11-libs/libfm-qt uses private Qt headers, lacks slot operator (was: x11-misc/pcmanfm-qt, media-gfx/lximage-qt: segfault after update to Qt-5.11.1)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
offending file in dev-qt/qtcore
qsharedpointer.cpp (text/x-c++src), 60.40 KB, created by
Michał Dec
on 2018-11-25 17:57:36 UTC
(
hide
)
Description:
offending file in dev-qt/qtcore
Filename:
MIME Type:
Creator:
Michał Dec
Created:
2018-11-25 17:57:36 UTC
Size:
60.40 KB
patch
obsolete
>/**************************************************************************** >** >** Copyright (C) 2016 The Qt Company Ltd. >** Copyright (C) 2016 Intel Corporation. >** Contact: https://www.qt.io/licensing/ >** >** This file is part of the QtCore module of the Qt Toolkit. >** >** $QT_BEGIN_LICENSE:LGPL$ >** Commercial License Usage >** Licensees holding valid commercial Qt licenses may use this file in >** accordance with the commercial license agreement provided with the >** Software or, alternatively, in accordance with the terms contained in >** a written agreement between you and The Qt Company. For licensing terms >** and conditions see https://www.qt.io/terms-conditions. For further >** information use the contact form at https://www.qt.io/contact-us. >** >** GNU Lesser General Public License Usage >** Alternatively, this file may be used under the terms of the GNU Lesser >** General Public License version 3 as published by the Free Software >** Foundation and appearing in the file LICENSE.LGPL3 included in the >** packaging of this file. Please review the following information to >** ensure the GNU Lesser General Public License version 3 requirements >** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. >** >** GNU General Public License Usage >** Alternatively, this file may be used under the terms of the GNU >** General Public License version 2.0 or (at your option) the GNU General >** Public license version 3 or any later version approved by the KDE Free >** Qt Foundation. The licenses are as published by the Free Software >** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 >** included in the packaging of this file. Please review the following >** information to ensure the GNU General Public License requirements will >** be met: https://www.gnu.org/licenses/gpl-2.0.html and >** https://www.gnu.org/licenses/gpl-3.0.html. >** >** $QT_END_LICENSE$ >** >****************************************************************************/ > >#include "qsharedpointer.h" > >// to be sure we aren't causing a namespace clash: >#include "qshareddata.h" > >/*! > \class QSharedPointer > \inmodule QtCore > \brief The QSharedPointer class holds a strong reference to a shared pointer > \since 4.5 > > \reentrant > > The QSharedPointer is an automatic, shared pointer in C++. It > behaves exactly like a normal pointer for normal purposes, > including respect for constness. > > QSharedPointer will delete the pointer it is holding when it goes > out of scope, provided no other QSharedPointer objects are > referencing it. > > A QSharedPointer object can be created from a normal pointer, > another QSharedPointer object or by promoting a > QWeakPointer object to a strong reference. > > \section1 Thread-Safety > > QSharedPointer and QWeakPointer are thread-safe and operate > atomically on the pointer value. Different threads can also access > the QSharedPointer or QWeakPointer pointing to the same object at > the same time without need for locking mechanisms. > > It should be noted that, while the pointer value can be accessed > in this manner, QSharedPointer and QWeakPointer provide no > guarantee about the object being pointed to. Thread-safety and > reentrancy rules for that object still apply. > > \section1 Other Pointer Classes > > Qt also provides two other pointer wrapper classes: QPointer and > QSharedDataPointer. They are incompatible with one another, since > each has its very different use case. > > QSharedPointer holds a shared pointer by means of an external > reference count (i.e., a reference counter placed outside the > object). Like its name indicates, the pointer value is shared > among all instances of QSharedPointer and QWeakPointer. The > contents of the object pointed to by the pointer should not be > considered shared, however: there is only one object. For that > reason, QSharedPointer does not provide a way to detach or make > copies of the pointed object. > > QSharedDataPointer, on the other hand, holds a pointer to shared > data (i.e., a class derived from QSharedData). It does so by means > of an internal reference count, placed in the QSharedData base > class. This class can, therefore, detach based on the type of > access made to the data being guarded: if it's a non-const access, > it creates a copy atomically for the operation to complete. > > QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except > that it only detaches if QExplicitlySharedDataPointer::detach() is > explicitly called (hence the name). > > QScopedPointer simply holds a pointer to a heap allocated object and > deletes it in its destructor. This class is useful when an object needs to > be heap allocated and deleted, but no more. QScopedPointer is lightweight, > it makes no use of additional structure or reference counting. > > Finally, QPointer holds a pointer to a QObject-derived object, but it > does so weakly. QWeakPointer has the same functionality, but its use for > that function is deprecated. > > \section1 Optional Pointer Tracking > > A feature of QSharedPointer that can be enabled at compile-time for > debugging purposes is a pointer tracking mechanism. When enabled, > QSharedPointer registers in a global set all the pointers that it tracks. > This allows one to catch mistakes like assigning the same pointer to two > QSharedPointer objects. > > This function is enabled by defining the \tt{QT_SHAREDPOINTER_TRACK_POINTERS} > macro before including the QSharedPointer header. > > It is safe to use this feature even with code compiled without the > feature. QSharedPointer will ensure that the pointer is removed from the > tracker even from code compiled without pointer tracking. > > Note, however, that the pointer tracking feature has limitations on > multiple- or virtual-inheritance (that is, in cases where two different > pointer addresses can refer to the same object). In that case, if a > pointer is cast to a different type and its value changes, > QSharedPointer's pointer tracking mechanism may fail to detect that the > object being tracked is the same. > > \omit > \section1 QSharedPointer internals > > QSharedPointer has two "private" members: the pointer itself being tracked > and a d-pointer. Those members are private to the class, but QSharedPointer > is friends with QWeakPointer and other QSharedPointer with different > template arguments. (On some compilers, template friends are not supported, > so the members are technically public) > > The reason for keeping the pointer value itself outside the d-pointer is > because of multiple inheritance needs. If you have two QSharedPointer > objects of different pointer types, but pointing to the same object in > memory, it could happen that the pointer values are different. The \tt > differentPointers autotest exemplifies this problem. The same thing could > happen in the case of virtual inheritance: a pointer of class matching > the virtual base has different address compared to the pointer of the > complete object. See the \tt virtualBaseDifferentPointers autotest for > this problem. > > The d pointer is a pointer to QtSharedPointer::ExternalRefCountData, but it > always points to one of the two classes derived from ExternalRefCountData. > > \section2 d-pointer > \section3 QtSharedPointer::ExternalRefCountData > > It is basically a reference-counted reference-counter plus a pointer to the > function to be used to delete the pointer. It has three members: \tt > strongref, \tt weakref, and \tt destroyer. The strong reference counter is > controlling the lifetime of the object tracked by QSharedPointer. A > positive value indicates that the object is alive. It's also the number of > QSharedObject instances that are attached to this Data. > > When the strong reference count decreases to zero, the object is deleted > (see below for information on custom deleters). The strong reference count > can also exceptionally be -1, indicating that there are no QSharedPointers > attached to an object, which is tracked too. The only case where this is > possible is that of QWeakPointers and QPointers tracking a QObject. Note > that QWeakPointers tracking a QObject is a deprecated feature as of Qt 5.0, > kept only for compatibility with Qt 4.x. > > The weak reference count controls the lifetime of the d-pointer itself. > It can be thought of as an internal/intrusive reference count for > ExternalRefCountData itself. This count is equal to the number of > QSharedPointers and QWeakPointers that are tracking this object. In case > the object is a QObject being tracked by QPointer, this number is increased > by 1, since QObjectPrivate tracks it too. > > The third member is a pointer to the function that is used to delete the > pointer being tracked. That happens when the destroy() function is called. > > The size of this class is the size of the two atomic ints plus the size of > a pointer. On 32-bit architectures, that's 12 bytes, whereas on 64-bit ones > it's 16 bytes. There is no padding. > > \section3 QtSharedPointer::ExternalRefCountWithCustomDeleter > > This class derives from ExternalRefCountData and is a template class. As > template parameters, it has the type of the pointer being tracked (\tt T) > and a \tt Deleter, which is anything. It adds two fields to its parent > class, matching those template parameters: a member of type \tt Deleter and > a member of type \tt T*. Those members are actually inside a template > struct of type CustomDeleter, which is partially-specialized for normal > deletion. See below for more details on that. > > The purpose of this class is to store the pointer to be deleted and the > deleter code along with the d-pointer. This allows the last strong > reference to call any arbitrary function that disposes of the object. For > example, this allows calling QObject::deleteLater() on a given object. > The pointer to the object is kept here because it needs to match the actual > deleter function's parameters, regardless of what template argument the > last QSharedPointer instance had. > > This class is never instantiated directly: the constructors and > destructor are private and, in C++11, deleted. Only the create() function > may be called to return an object of this type. See below for construction > details. > > The size of this class depends on the size of \tt Deleter. If it's an empty > functor (i.e., no members), ABIs generally assign it the size of 1. But > given that it's followed by a pointer, padding bytes may be inserted so > that the alignment of the class and of the pointer are correct. In that > case, the size of this class is 12+4+4 = 20 bytes on 32-bit architectures, > or 16+8+8 = 40 bytes on 64-bit architectures. If \tt Deleter is a function > pointer, the size should be the same as the empty structure case. If \tt > Deleter is a pointer to a member function (PMF), the size will be bigger > and will depend on the ABI. For architectures using the Itanium C++ ABI, a > PMF is twice the size of a normal pointer. In that case, the size of this > structure will be 12+8+4 = 24 bytes on 32-bit architectures, 16+16+8 = 40 > bytes on 64-bit ones. > > If the deleter was not specified when creating the QSharedPointer object > (i.e., if a standard \tt delete call is expected), then there's an > optimization that avoids the need to store another function pointer in > ExternalRefCountWithCustomDeleter. Instead, a template specialization makes > a direct delete call. The size of the structure, in this case, is 12+4 = 16 > bytes on 32-bit architectures, 16+8 = 24 bytes on 64-bit ones. > > \section3 QtSharedPointer::ExternalRefCountWithContiguousData > > This class also derives from ExternalRefCountData and it is > also a template class. The template parameter is the type \tt T of the > class which QSharedPointer tracks. It adds only one member to its parent, > which is of type \tt T (the actual type, not a pointer to it). > > The purpose of this class is to lay the \tt T object out next to the > reference counts, saving one memory allocation per shared pointer. This > is particularly interesting for small \tt T or for the cases when there > are few if any QWeakPointer tracking the object. This class exists to > implement the QSharedPointer::create() call. > > Like ExternalRefCountWithCustomDeleter, this class is never instantiated > directly. This class also provides a create() member that returns the > pointer, and hides its constructors and destructor. With C++11, they're > deleted. > > The size of this class depends on the size of \tt T. > > \section3 Instantiating ExternalRefCountWithCustomDeleter and ExternalRefCountWithContiguousData > > Like explained above, these classes have private constructors. Moreover, > they are not defined anywhere, so trying to call \tt{new ClassType} would > result in a compilation or linker error. Instead, these classes must be > constructed via their create() methods. > > Instead of instantiating the class by the normal way, the create() method > calls \tt{operator new} directly with the size of the class, then calls > the parent class's constructor only (that is, ExternalRefCountData's constructor). > This ensures that the inherited members are initialised properly. > > After initialising the base class, the > ExternalRefCountWithCustomDeleter::create() function initialises the new > members directly, by using the placement \tt{operator new}. In the case > of the ExternalRefCountWithContiguousData::create() function, the address > to the still-uninitialised \tt T member is saved for the callee to use. > The member is only initialised in QSharedPointer::create(), so that we > avoid having many variants of the internal functions according to the > arguments in use for calling the constructor. > > When initialising the parent class, the create() functions pass the > address of the static deleter() member function. That is, when the > destroy() function is called by QSharedPointer, the deleter() functions > are called instead. These functions static_cast the ExternalRefCountData* > parameter to their own type and execute their deletion: for the > ExternalRefCountWithCustomDeleter::deleter() case, it runs the user's > custom deleter, then destroys the deleter; for > ExternalRefCountWithContiguousData::deleter, it simply calls the \tt T > destructor directly. > > Only one non-inline function is required per template, which is > the deleter() static member. All the other functions can be inlined. > What's more, the address of deleter() is calculated only in code, which > can be resolved at link-time if the linker can determine that the > function lies in the current application or library module (since these > classes are not exported, that is the case for Windows or for builds with > \tt{-fvisibility=hidden}). > > \section3 Modifications due to pointer-tracking > > To ensure that pointers created with pointer-tracking enabled get > un-tracked when destroyed, even if destroyed by code compiled without the > feature, QSharedPointer modifies slightly the instructions of the > previous sections. > > When ExternalRefCountWithCustomDeleter or > ExternalRefCountWithContiguousData are used, their create() functions > will set the ExternalRefCountData::destroyer function > pointer to safetyCheckDeleter() instead. These static member functions > simply call internalSafetyCheckRemove() before passing control to the > normal deleter() function. > > If neither custom deleter nor QSharedPointer::create() are used, then > QSharedPointer uses a custom deleter of its own: the normalDeleter() > function, which simply calls \tt delete. By using a custom deleter, the > safetyCheckDeleter() procedure described above kicks in. > > \endomit > > \sa QSharedDataPointer, QWeakPointer, QScopedPointer, QEnableSharedFromThis >*/ > >/*! > \class QWeakPointer > \inmodule QtCore > \brief The QWeakPointer class holds a weak reference to a shared pointer > \since 4.5 > \reentrant > > The QWeakPointer is an automatic weak reference to a > pointer in C++. It cannot be used to dereference the pointer > directly, but it can be used to verify if the pointer has been > deleted or not in another context. > > QWeakPointer objects can only be created by assignment from a > QSharedPointer. > > It's important to note that QWeakPointer provides no automatic casting > operators to prevent mistakes from happening. Even though QWeakPointer > tracks a pointer, it should not be considered a pointer itself, since it > doesn't guarantee that the pointed object remains valid. > > Therefore, to access the pointer that QWeakPointer is tracking, you must > first promote it to QSharedPointer and verify if the resulting object is > null or not. QSharedPointer guarantees that the object isn't deleted, so > if you obtain a non-null object, you may use the pointer. See > QWeakPointer::toStrongRef() for an example. > > QWeakPointer also provides the QWeakPointer::data() method that returns > the tracked pointer without ensuring that it remains valid. This function > is provided if you can guarantee by external means that the object will > not get deleted (or if you only need the pointer value) and the cost of > creating a QSharedPointer using toStrongRef() is too high. > > \omit > \section1 QWeakPointer internals > > QWeakPointer shares most of its internal functionality with > \l{QSharedPointer#qsharedpointer-internals}{QSharedPointer}, so see that > class's internal documentation for more information. > > QWeakPointer requires an external reference counter in order to operate. > Therefore, it is incompatible by design with \l QSharedData-derived > classes. > > It has a special QObject constructor, which works by calling > QtSharedPointer::ExternalRefCountData::getAndRef, which retrieves the > d-pointer from QObjectPrivate. If one isn't set yet, that function > creates the d-pointer and atomically sets it. > > If getAndRef needs to create a d-pointer, it sets the strongref to -1, > indicating that the QObject is not shared: QWeakPointer is used only to > determine whether the QObject has been deleted. In that case, it cannot > be upgraded to QSharedPointer (see the previous section). > > \endomit > > \sa QSharedPointer, QScopedPointer >*/ > >/*! > \class QEnableSharedFromThis > \inmodule QtCore > \brief A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer > \since 5.4 > > You can inherit this class when you need to create a QSharedPointer > from any instance of a class; for instance, from within the > object itself. The key point is that the technique of > just returning QSharedPointer<T>(this) can not be used, because > this winds up creating multiple distinct QSharedPointer objects > with separate reference counts. For this reason you must never > create more than one QSharedPointer from the same raw pointer. > > QEnableSharedFromThis defines two member functions called > sharedFromThis() that return a QSharedPointer<T> and > QSharedPointer<const T>, depending on constness, to \c this: > > \code > class Y: public QEnableSharedFromThis<Y> > { > public: > QSharedPointer<Y> f() > { > return sharedFromThis(); > } > }; > > int main() > { > QSharedPointer<Y> p(new Y()); > QSharedPointer<Y> y = p->f(); > Q_ASSERT(p == y); // p and q must share ownership > } > \endcode > > It is also possible to get a shared pointer from an object outside of > the class itself. This is especially useful in code that provides an > interface to scripts, where it is currently not possible to use shared > pointers. For example: > > \code > class ScriptInterface : public QObject > { > Q_OBJECT > > // ... > > public slots: > void slotCalledByScript(Y *managedBySharedPointer) > { > QSharedPointer<Y> yPtr = managedBySharedPointer->sharedFromThis(); > // Some other code unrelated to scripts that expects a QSharedPointer<Y> ... > } > }; > \endcode >*/ > >/*! > \fn template <class T> QSharedPointer<T>::QSharedPointer() > > Creates a QSharedPointer that points to null (0). >*/ > >/*! > \fn template <class T> QSharedPointer<T>::~QSharedPointer() > > Destroys this QSharedPointer object. If it is the last reference to > the pointer stored, this will delete the pointer as well. >*/ > >/*! > \fn template <class T> template <typename X> QSharedPointer<T>::QSharedPointer(X *ptr) > > Creates a QSharedPointer that points to \a ptr. The pointer \a ptr > becomes managed by this QSharedPointer and must not be passed to > another QSharedPointer object or deleted outside this object. > > Since Qt 5.8, when the last reference to this QSharedPointer gets > destroyed, \a ptr will be deleted by calling \c X's destructor (even if \c > X is not the same as QSharedPointer's template parameter \c T). Previously, > the destructor for \c T was called. >*/ > >/*! > \fn template <class T> template <typename X, typename Deleter> QSharedPointer<T>::QSharedPointer(X *ptr, Deleter d) > > Creates a QSharedPointer that points to \a ptr. The pointer \a ptr > becomes managed by this QSharedPointer and must not be passed to > another QSharedPointer object or deleted outside this object. > > The deleter parameter \a d specifies the custom deleter for this > object. The custom deleter is called, instead of the operator delete(), > when the strong reference count drops to 0. This is useful, > for instance, for calling \l {QObject::}{deleteLater()} on a QObject instead: > > \code > static void doDeleteLater(MyObject *obj) > { > obj->deleteLater(); > } > > void otherFunction() > { > QSharedPointer<MyObject> obj = > QSharedPointer<MyObject>(new MyObject, doDeleteLater); > > // continue using obj > obj.clear(); // calls obj->deleteLater(); > } > \endcode > > Note that the custom deleter function will be called with a pointer to type > \c X, even if the QSharedPointer template parameter \c T is not the same. > > It is also possible to specify a member function directly, as in: > \code > QSharedPointer<MyObject> obj = > QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater); > \endcode > > \sa clear() >*/ > >/*! > \fn template <class T> QSharedPointer<T>::QSharedPointer(std::nullptr_t) > \since 5.8 > > Creates a QSharedPointer that is null. This is equivalent to the > QSharedPointer default constructor. >*/ > >/*! > \fn template <class T> template <typename Deleter> QSharedPointer<T>::QSharedPointer(std::nullptr_t, Deleter d) > \since 5.8 > > Creates a QSharedPointer that is null. This is equivalent to the > QSharedPointer default constructor. > > The deleter parameter \a d specifies the custom deleter for this > object. The custom deleter is called, instead of the operator > delete(), when the strong reference count drops to 0. >*/ > >/*! > \fn template <class T> QSharedPointer<T>::QSharedPointer(const QSharedPointer<T> &other) > > Creates a QSharedPointer object that shares \a other's pointer. > > If \tt T is a derived type of the template parameter of this class, > QSharedPointer will perform an automatic cast. Otherwise, you will > get a compiler error. >*/ > >/*! > \fn template <class T> QSharedPointer<T>::QSharedPointer(const QWeakPointer<T> &other) > > Creates a QSharedPointer by promoting the weak reference \a other > to strong reference and sharing its pointer. > > If \tt T is a derived type of the template parameter of this > class, QSharedPointer will perform an automatic cast. Otherwise, > you will get a compiler error. > > \sa QWeakPointer::toStrongRef() >*/ > >/*! > \fn template <class T> QSharedPointer &QSharedPointer<T>::operator=(const QSharedPointer<T> &other) > > Makes this object share \a other's pointer. The current pointer > reference is discarded and, if it was the last, the pointer will > be deleted. > > If \tt T is a derived type of the template parameter of this > class, QSharedPointer will perform an automatic cast. Otherwise, > you will get a compiler error. >*/ > >/*! > \fn template <class T> QSharedPointer &QSharedPointer<T>::operator=(const QWeakPointer<T> &other) > > Promotes \a other to a strong reference and makes this object > share a reference to the pointer referenced by it. The current pointer > reference is discarded and, if it was the last, the pointer will > be deleted. > > If \tt T is a derived type of the template parameter of this > class, QSharedPointer will perform an automatic cast. Otherwise, > you will get a compiler error. >*/ > >/*! > \fn template <class T> void QSharedPointer<T>::swap(QSharedPointer<T> &other); > \since 5.3 > > Swaps this shared pointer instance with \a other. This function is > very fast and never fails. >*/ > >/*! > \fn template <class T> T *QSharedPointer<T>::data() const > > Returns the value of the pointer referenced by this object. > > Note: do not delete the pointer returned by this function or pass > it to another function that could delete it, including creating > QSharedPointer or QWeakPointer objects. >*/ > >/*! > \fn template <class T> T *QSharedPointer<T>::get() const > \since 5.11 > > Same as data(). > > This function is provided for API compatibility with \c{std::shared_ptr}. >*/ > >/*! > \fn template <class T> T &QSharedPointer<T>::operator *() const > > Provides access to the shared pointer's members. > > \sa isNull() >*/ > >/*! > \fn template <class T> T *QSharedPointer<T>::operator ->() const > > Provides access to the shared pointer's members. > > \sa isNull() >*/ > >/*! > \fn template <class T> bool QSharedPointer<T>::isNull() const > > Returns \c true if this object is holding a reference to a null > pointer. >*/ > >/*! > \fn template <class T> QSharedPointer<T>::operator bool() const > > Returns \c true if this object is not null. This function is suitable > for use in \tt if-constructs, like: > > \code > if (sharedptr) { ... } > \endcode > > \sa isNull() >*/ > >/*! > \fn template <class T> bool QSharedPointer<T>::operator !() const > > Returns \c true if this object is null. This function is suitable > for use in \tt if-constructs, like: > > \code > if (!sharedptr) { ... } > \endcode > > \sa isNull() >*/ > >/*! > \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::staticCast() const > > Performs a static cast from this pointer's type to \tt X and returns > a QSharedPointer that shares the reference. This function can be > used for up- and for down-casting, but is more useful for > up-casting. > > Note: the template type \c X must have the same const and volatile > qualifiers as the template of this object, or the cast will > fail. Use constCast() if you need to drop those qualifiers. > > \sa dynamicCast(), constCast(), qSharedPointerCast() >*/ > >/*! > \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::dynamicCast() const > > Performs a dynamic cast from this pointer's type to \tt X and > returns a QSharedPointer that shares the reference. If this > function is used to up-cast, then QSharedPointer will perform a \tt > dynamic_cast, which means that if the object being pointed by this > QSharedPointer is not of type \tt X, the returned object will be > null. > > Note: the template type \c X must have the same const and volatile > qualifiers as the template of this object, or the cast will > fail. Use constCast() if you need to drop those qualifiers. > > \sa qSharedPointerDynamicCast() >*/ > >/*! > \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::constCast() const > > Performs a \tt const_cast from this pointer's type to \tt X and returns > a QSharedPointer that shares the reference. This function can be > used for up- and for down-casting, but is more useful for > up-casting. > > \sa isNull(), qSharedPointerConstCast() >*/ > >/*! > \fn template <class T> template <class X> QSharedPointer<X> QSharedPointer<T>::objectCast() const > \since 4.6 > > Performs a \l qobject_cast() from this pointer's type to \tt X and > returns a QSharedPointer that shares the reference. If this > function is used to up-cast, then QSharedPointer will perform a \tt > qobject_cast, which means that if the object being pointed by this > QSharedPointer is not of type \tt X, the returned object will be > null. > > Note: the template type \c X must have the same const and volatile > qualifiers as the template of this object, or the cast will > fail. Use constCast() if you need to drop those qualifiers. > > \sa qSharedPointerObjectCast() >*/ > >/*! > \fn template <class T> QSharedPointer<T> QSharedPointer<T>::create() > \since 5.1 > > Creates a QSharedPointer object and allocates a new item of type \tt T. The > QSharedPointer internals and the object are allocated in one single memory > allocation, which could help reduce memory fragmentation in a long-running > application. > > This function calls the default constructor for type \tt T. >*/ > >/*! > \fn template <class T> QSharedPointer<T> QSharedPointer<T>::create(...) > \overload > \since 5.1 > > Creates a QSharedPointer object and allocates a new item of type \tt T. The > QSharedPointer internals and the object are allocated in one single memory > allocation, which could help reduce memory fragmentation in a long-running > application. > > This function will attempt to call a constructor for type \tt T that can > accept all the arguments passed. Arguments will be perfectly-forwarded. > > \note This function is only fully available with a C++11 compiler that > supports perfect forwarding of an arbitrary number of arguments. > > If the compiler does not support the necessary C++11 features, > then a restricted version is available since Qt 5.4: you may pass > one (but just one) argument, and it will always be passed by const > reference. > > If you target Qt before version 5.4, you must use the overload > that calls the default constructor. >*/ > >/*! > \fn template <class T> QWeakPointer<T> QSharedPointer<T>::toWeakRef() const > > Returns a weak reference object that shares the pointer referenced > by this object. > > \sa QWeakPointer::QWeakPointer() >*/ > >/*! > \fn template <class T> void QSharedPointer<T>::clear() > > Clears this QSharedPointer object, dropping the reference that it > may have had to the pointer. If this was the last reference, then > the pointer itself will be deleted. >*/ > >/*! > \fn template <class T> void QSharedPointer<T>::reset() > \since 5.0 > > Same as clear(). For std::shared_ptr compatibility. >*/ > >/*! > \fn template <class T> void QSharedPointer<T>::reset(T *t) > \since 5.0 > > Resets this QSharedPointer object to point to \a t > instead. Equivalent to: > \code > QSharedPointer<T> other(t); this->swap(other); > \endcode >*/ > >/*! > \fn template <class T> template <typename Deleter> void QSharedPointer<T>::reset(T *t, Deleter deleter) > \since 5.0 > > Resets this QSharedPointer object to point to \a t > instead, with the Deleter \a deleter. Equivalent to: > \code > QSharedPointer<T> other(t, deleter); this->swap(other); > \endcode >*/ > >/*! > \fn template <class T> QWeakPointer<T>::QWeakPointer() > > Creates a QWeakPointer that points to nothing. >*/ > >/*! > \fn template <class T> QWeakPointer<T>::~QWeakPointer() > > Destroys this QWeakPointer object. The pointer referenced > by this object will not be deleted. >*/ > >/*! > \fn template <class T> QWeakPointer<T>::QWeakPointer(const QWeakPointer<T> &other) > > Creates a QWeakPointer that holds a weak reference to the > pointer referenced by \a other. > > If \tt T is a derived type of the template parameter of this > class, QWeakPointer will perform an automatic cast. Otherwise, > you will get a compiler error. >*/ > >/*! > \fn template <class T> QWeakPointer<T>::QWeakPointer(const QSharedPointer<T> &other) > > Creates a QWeakPointer that holds a weak reference to the > pointer referenced by \a other. > > If \tt T is a derived type of the template parameter of this > class, QWeakPointer will perform an automatic cast. Otherwise, > you will get a compiler error. >*/ > >/*! > \fn template <class T> QWeakPointer<T>::QWeakPointer(const QObject *other) > \since 4.6 > \deprecated > > Creates a QWeakPointer that holds a weak reference directly to the > QObject \a other. This constructor is only available if the template type > \tt T is QObject or derives from it (otherwise a compilation error will > result). > > You can use this constructor with any QObject, even if they were not > created with \l QSharedPointer. > > Note that QWeakPointers created this way on arbitrary QObjects usually > cannot be promoted to QSharedPointer. > > \sa QSharedPointer, QPointer >*/ > >/*! > \fn template <class T> QWeakPointer &QWeakPointer<T>::operator=(const QObject *other) > \since 4.6 > \deprecated > > Makes this QWeakPointer hold a weak reference directly to the QObject > \a other. This function is only available if the template type \tt T is > QObject or derives from it. > > \sa QPointer >*/ > >/*! > \fn template <class T> QWeakPointer &QWeakPointer<T>::operator=(const QWeakPointer<T> &other) > > Makes this object share \a other's pointer. The current pointer > reference is discarded but is not deleted. > > If \tt T is a derived type of the template parameter of this > class, QWeakPointer will perform an automatic cast. Otherwise, > you will get a compiler error. >*/ > >/*! > \fn template <class T> QWeakPointer &QWeakPointer<T>::operator=(const QSharedPointer<T> &other) > > Makes this object share \a other's pointer. The current pointer > reference is discarded but is not deleted. > > If \tt T is a derived type of the template parameter of this > class, QWeakPointer will perform an automatic cast. Otherwise, > you will get a compiler error. >*/ > >/*! > \fn template <class T> void QWeakPointer<T>::swap(QWeakPointer<T> &other) > \since 5.4 > > Swaps this weak pointer instance with \a other. This function is > very fast and never fails. >*/ > >/*! > \fn template <class T> bool QWeakPointer<T>::isNull() const > > Returns \c true if this object is holding a reference to a null > pointer. > > Note that, due to the nature of weak references, the pointer that > QWeakPointer references can become null at any moment, so > the value returned from this function can change from false to > true from one call to the next. >*/ > >/*! > \fn template <class T> QWeakPointer<T>::operator bool() const > > Returns \c true if this object is not null. This function is suitable > for use in \tt if-constructs, like: > > \code > if (weakref) { ... } > \endcode > > Note that, due to the nature of weak references, the pointer that > QWeakPointer references can become null at any moment, so > the value returned from this function can change from true to > false from one call to the next. > > \sa isNull() >*/ > >/*! > \fn template <class T> bool QWeakPointer<T>::operator !() const > > Returns \c true if this object is null. This function is suitable > for use in \tt if-constructs, like: > > \code > if (!weakref) { ... } > \endcode > > Note that, due to the nature of weak references, the pointer that > QWeakPointer references can become null at any moment, so > the value returned from this function can change from false to > true from one call to the next. > > \sa isNull() >*/ > >/*! > \fn template <class T> T *QWeakPointer<T>::data() const > \since 4.6 > > Returns the value of the pointer being tracked by this QWeakPointer, > \b without ensuring that it cannot get deleted. To have that guarantee, > use toStrongRef(), which returns a QSharedPointer object. If this > function can determine that the pointer has already been deleted, it > returns 0. > > It is ok to obtain the value of the pointer and using that value itself, > like for example in debugging statements: > > \code > qDebug("Tracking %p", weakref.data()); > \endcode > > However, dereferencing the pointer is only allowed if you can guarantee > by external means that the pointer does not get deleted. For example, > if you can be certain that no other thread can delete it, nor the > functions that you may call. > > If that is the case, then the following code is valid: > > \code > // this pointer cannot be used in another thread > // so other threads cannot delete it > QWeakPointer<int> weakref = obtainReference(); > > Object *obj = weakref.data(); > if (obj) { > // if the pointer wasn't deleted yet, we know it can't get > // deleted by our own code here nor the functions we call > otherFunction(obj); > } > \endcode > > Use this function with care. > > \sa isNull(), toStrongRef() >*/ > >/*! > \fn template <class T> QSharedPointer<T> QWeakPointer<T>::toStrongRef() const > > Promotes this weak reference to a strong one and returns a > QSharedPointer object holding that reference. When promoting to > QSharedPointer, this function verifies if the object has been deleted > already or not. If it hasn't, this function increases the reference > count to the shared object, thus ensuring that it will not get > deleted. > > Since this function can fail to obtain a valid strong reference to the > shared object, you should always verify if the conversion succeeded, > by calling QSharedPointer::isNull() on the returned object. > > For example, the following code promotes a QWeakPointer that was held > to a strong reference and, if it succeeded, it prints the value of the > integer that was held: > > \code > QWeakPointer<int> weakref; > > // ... > > QSharedPointer<int> strong = weakref.toStrongRef(); > if (strong) > qDebug() << "The value is:" << *strong; > else > qDebug() << "The value has already been deleted"; > \endcode > > \sa QSharedPointer::QSharedPointer() >*/ > >/*! > \fn template <class T> QSharedPointer<T> QWeakPointer<T>::lock() const > \since 5.4 > > Same as toStrongRef(). > > This function is provided for API compatibility with std::weak_ptr. >*/ > >/*! > \fn template <class T> void QWeakPointer<T>::clear() > > Clears this QWeakPointer object, dropping the reference that it > may have had to the pointer. >*/ > >/*! > \fn template <class T> QSharedPointer<T> QEnableSharedFromThis<T>::sharedFromThis() > \since 5.4 > > If \c this (that is, the subclass instance invoking this method) is being > managed by a QSharedPointer, returns a shared pointer instance pointing to > \c this; otherwise returns a QSharedPointer holding a null pointer. >*/ > >/*! > \fn template <class T> QSharedPointer<const T> QEnableSharedFromThis<T>::sharedFromThis() const > \overload > \since 5.4 > > Const overload of sharedFromThis(). >*/ > >/*! > \fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) > \relates QSharedPointer > > Returns \c true if the pointer referenced by \a ptr1 is the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) > \relates QSharedPointer > > Returns \c true if the pointer referenced by \a ptr1 is not the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) > \relates QSharedPointer > > Returns \c true if the pointer referenced by \a ptr1 is the > same pointer as \a ptr2. > > If \a ptr2's type is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > type is not a base or a derived type from this > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) > \relates QSharedPointer > > Returns \c true if the pointer referenced by \a ptr1 is not the > same pointer as \a ptr2. > > If \a ptr2's type is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > type is not a base or a derived type from this > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) > \relates QSharedPointer > > Returns \c true if the pointer \a ptr1 is the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's type, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's type, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) > \relates QSharedPointer > > Returns \c true if the pointer \a ptr1 is not the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's type, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's type, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) > \relates QWeakPointer > > Returns \c true if the pointer referenced by \a ptr1 is the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) > \relates QWeakPointer > > Returns \c true if the pointer referenced by \a ptr1 is not the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class T> template <class X> bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2) > \relates QWeakPointer > > Returns \c true if the pointer referenced by \a ptr1 is the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class T> bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) > \relates QSharedPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a lhs is a null pointer. > > \sa QSharedPointer::isNull() >*/ > >/*! > \fn template <class T> bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) > \relates QSharedPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a rhs is a null pointer. > > \sa QSharedPointer::isNull() >*/ > >/*! > \fn template <class T> bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) > \relates QSharedPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a lhs is a valid (i.e. > non-null) pointer. > > \sa QSharedPointer::isNull() >*/ > >/*! > \fn template <class T> bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) > \relates QSharedPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a rhs is a valid (i.e. > non-null) pointer. > > \sa QSharedPointer::isNull() >*/ > >/*! > \fn template <class T> bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) > \relates QWeakPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a lhs is a null pointer. > > \sa QWeakPointer::isNull() >*/ > >/*! > \fn template <class T> bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) > \relates QWeakPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a rhs is a null pointer. > > \sa QWeakPointer::isNull() >*/ > >/*! > \fn template <class T> bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) > \relates QWeakPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a lhs is a valid (i.e. > non-null) pointer. > > \sa QWeakPointer::isNull() >*/ > >/*! > \fn template <class T> bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) > \relates QWeakPointer > \since 5.8 > > Returns \c true if the pointer referenced by \a rhs is a valid (i.e. > non-null) pointer. > > \sa QWeakPointer::isNull() >*/ > >/*! > \fn template <class T> template <class X> bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2) > \relates QWeakPointer > > Returns \c true if the pointer referenced by \a ptr1 is not the > same pointer as that referenced by \a ptr2. > > If \a ptr2's template parameter is different from \a ptr1's, > QSharedPointer will attempt to perform an automatic \tt static_cast > to ensure that the pointers being compared are equal. If \a ptr2's > template parameter is not a base or a derived type from > \a ptr1's, you will get a compiler error. >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other) > \relates QSharedPointer > > Returns a shared pointer to the pointer held by \a other, cast to > type \tt X. The types \tt T and \tt X must belong to one > hierarchy for the \tt static_cast to succeed. > > Note that \tt X must have the same cv-qualifiers (\tt const and > \tt volatile) that \tt T has, or the code will fail to > compile. Use qSharedPointerConstCast to cast away the constness. > > \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast() >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other) > \relates QSharedPointer > \relates QWeakPointer > > Returns a shared pointer to the pointer held by \a other, cast to > type \tt X. The types \tt T and \tt X must belong to one > hierarchy for the \tt static_cast to succeed. > > The \a other object is converted first to a strong reference. If > that conversion fails (because the object it's pointing to has > already been deleted), this function returns a null > QSharedPointer. > > Note that \tt X must have the same cv-qualifiers (\tt const and > \tt volatile) that \tt T has, or the code will fail to > compile. Use qSharedPointerConstCast to cast away the constness. > > \sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast() >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src) > \relates QSharedPointer > > Returns a shared pointer to the pointer held by \a src, using a > dynamic cast to type \tt X to obtain an internal pointer of the > appropriate type. If the \tt dynamic_cast fails, the object > returned will be null. > > Note that \tt X must have the same cv-qualifiers (\tt const and > \tt volatile) that \tt T has, or the code will fail to > compile. Use qSharedPointerConstCast to cast away the constness. > > \sa QSharedPointer::dynamicCast(), qSharedPointerCast(), qSharedPointerConstCast() >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src) > \relates QSharedPointer > \relates QWeakPointer > > Returns a shared pointer to the pointer held by \a src, using a > dynamic cast to type \tt X to obtain an internal pointer of the > appropriate type. If the \tt dynamic_cast fails, the object > returned will be null. > > The \a src object is converted first to a strong reference. If > that conversion fails (because the object it's pointing to has > already been deleted), this function also returns a null > QSharedPointer. > > Note that \tt X must have the same cv-qualifiers (\tt const and > \tt volatile) that \tt T has, or the code will fail to > compile. Use qSharedPointerConstCast to cast away the constness. > > \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast() >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src) > \relates QSharedPointer > > Returns a shared pointer to the pointer held by \a src, cast to > type \tt X. The types \tt T and \tt X must belong to one > hierarchy for the \tt const_cast to succeed. The \tt const and \tt > volatile differences between \tt T and \tt X are ignored. > > \sa QSharedPointer::constCast(), qSharedPointerCast(), qSharedPointerDynamicCast() >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src) > \relates QSharedPointer > \relates QWeakPointer > > Returns a shared pointer to the pointer held by \a src, cast to > type \tt X. The types \tt T and \tt X must belong to one > hierarchy for the \tt const_cast to succeed. The \tt const and > \tt volatile differences between \tt T and \tt X are ignored. > > The \a src object is converted first to a strong reference. If > that conversion fails (because the object it's pointing to has > already been deleted), this function returns a null > QSharedPointer. > > \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerDynamicCast() >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src) > \relates QSharedPointer > \since 4.6 > > \brief The qSharedPointerObjectCast function is for casting a shared pointer. > > Returns a shared pointer to the pointer held by \a src, using a > \l qobject_cast() to type \tt X to obtain an internal pointer of the > appropriate type. If the \tt qobject_cast fails, the object > returned will be null. > > Note that \tt X must have the same cv-qualifiers (\tt const and > \tt volatile) that \tt T has, or the code will fail to > compile. Use qSharedPointerConstCast to cast away the constness. > > \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast() >*/ > >/*! > \fn template <class X> template <class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src) > \relates QSharedPointer > \relates QWeakPointer > \since 4.6 > > \brief The qSharedPointerObjectCast function is for casting a shared pointer. > > Returns a shared pointer to the pointer held by \a src, using a > \l qobject_cast() to type \tt X to obtain an internal pointer of the > appropriate type. If the \tt qobject_cast fails, the object > returned will be null. > > The \a src object is converted first to a strong reference. If > that conversion fails (because the object it's pointing to has > already been deleted), this function also returns a null > QSharedPointer. > > Note that \tt X must have the same cv-qualifiers (\tt const and > \tt volatile) that \tt T has, or the code will fail to > compile. Use qSharedPointerConstCast to cast away the constness. > > \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast() >*/ > > >/*! > \fn template <class X> template <class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src) > \relates QWeakPointer > > Returns a weak pointer to the pointer held by \a src, cast to > type \tt X. The types \tt T and \tt X must belong to one > hierarchy for the \tt static_cast to succeed. > > Note that \tt X must have the same cv-qualifiers (\tt const and > \tt volatile) that \tt T has, or the code will fail to > compile. Use qSharedPointerConstCast to cast away the constness. >*/ > >#include <qset.h> >#include <qmutex.h> > >#if !defined(QT_NO_QOBJECT) >#include "private/qobject_p.h" > >QT_BEGIN_NAMESPACE > >/*! > \internal > This function is called for a just-created QObject \a obj, to enable > the use of QSharedPointer and QWeakPointer in the future. > */ >void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *, bool) >{} > >/*! > \internal > This function is called when a QSharedPointer is created from a QWeakPointer > > We check that the QWeakPointer was really created from a QSharedPointer, and > not from a QObject. >*/ >void QtSharedPointer::ExternalRefCountData::checkQObjectShared(const QObject *) >{ > if (strongref.load() < 0) > qWarning("QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer"); >} > >QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj) >{ > Q_ASSERT(obj); > QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); > Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted"); > > ExternalRefCountData *that = d->sharedRefcount.load(); > if (that) { > that->weakref.ref(); > return that; > } > > // we can create the refcount data because it doesn't exist > ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized); > x->strongref.store(-1); > x->weakref.store(2); // the QWeakPointer that called us plus the QObject itself > if (!d->sharedRefcount.testAndSetRelease(0, x)) { > delete x; > x = d->sharedRefcount.loadAcquire(); > x->weakref.ref(); > } > return x; >} > >/** > \internal > Returns a QSharedPointer<QObject> if the variant contains > a QSharedPointer<T> where T inherits QObject. Otherwise the behaviour is undefined. >*/ >QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant) >{ > Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::SharedPointerToQObject); > return *reinterpret_cast<const QSharedPointer<QObject>*>(variant.constData()); >} > >/** > \internal > Returns a QWeakPointer<QObject> if the variant contains > a QWeakPointer<T> where T inherits QObject. Otherwise the behaviour is undefined. >*/ >QWeakPointer<QObject> QtSharedPointer::weakPointerFromVariant_internal(const QVariant &variant) >{ > Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::WeakPointerToQObject || QMetaType::typeFlags(variant.userType()) & QMetaType::TrackingPointerToQObject); > return *reinterpret_cast<const QWeakPointer<QObject>*>(variant.constData()); >} > >QT_END_NAMESPACE > >#endif > > > >//# define QT_SHARED_POINTER_BACKTRACE_SUPPORT ># ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT ># if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE) ># define BACKTRACE_SUPPORTED ># elif defined(Q_OS_MAC) ># define BACKTRACE_SUPPORTED ># endif ># endif > ># if defined(BACKTRACE_SUPPORTED) ># include <sys/types.h> ># include <execinfo.h> ># include <stdio.h> ># include <unistd.h> ># include <sys/wait.h> > >QT_BEGIN_NAMESPACE > >static inline QByteArray saveBacktrace() __attribute__((always_inline)); >static inline QByteArray saveBacktrace() >{ > static const int maxFrames = 32; > > QByteArray stacktrace; > stacktrace.resize(sizeof(void*) * maxFrames); > int stack_size = backtrace((void**)stacktrace.data(), maxFrames); > stacktrace.resize(sizeof(void*) * stack_size); > > return stacktrace; >} > >static void printBacktrace(QByteArray stacktrace) >{ > void *const *stack = (void *const *)stacktrace.constData(); > int stack_size = stacktrace.size() / sizeof(void*); > char **stack_symbols = backtrace_symbols(stack, stack_size); > > int filter[2]; > pid_t child = -1; > if (pipe(filter) != -1) > child = fork(); > if (child == 0) { > // child process > dup2(fileno(stderr), fileno(stdout)); > dup2(filter[0], fileno(stdin)); > close(filter[0]); > close(filter[1]); > execlp("c++filt", "c++filt", "-n", NULL); > > // execlp failed > execl("/bin/cat", "/bin/cat", NULL); > _exit(127); > } > > // parent process > close(filter[0]); > FILE *output; > if (child == -1) { > // failed forking > close(filter[1]); > output = stderr; > } else { > output = fdopen(filter[1], "w"); > } > > fprintf(stderr, "Backtrace of the first creation (most recent frame first):\n"); > for (int i = 0; i < stack_size; ++i) { > if (strlen(stack_symbols[i])) > fprintf(output, "#%-2d %s\n", i, stack_symbols[i]); > else > fprintf(output, "#%-2d %p\n", i, stack[i]); > } > > if (child != -1) { > fclose(output); > waitpid(child, 0, 0); > } >} > >QT_END_NAMESPACE > ># endif // BACKTRACE_SUPPORTED > >namespace { > QT_USE_NAMESPACE > struct Data { > const volatile void *pointer; ># ifdef BACKTRACE_SUPPORTED > QByteArray backtrace; ># endif > }; > > class KnownPointers > { > public: > QMutex mutex; > QHash<const void *, Data> dPointers; > QHash<const volatile void *, const void *> dataPointers; > }; >} > >Q_GLOBAL_STATIC(KnownPointers, knownPointers) > >QT_BEGIN_NAMESPACE > >namespace QtSharedPointer { > Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck(); >} > >/*! > \internal >*/ >void QtSharedPointer::internalSafetyCheckAdd(const void *d_ptr, const volatile void *ptr) >{ > KnownPointers *const kp = knownPointers(); > if (!kp) > return; // end-game: the application is being destroyed already > > QMutexLocker lock(&kp->mutex); > Q_ASSERT(!kp->dPointers.contains(d_ptr)); > > //qDebug("Adding d=%p value=%p", d_ptr, ptr); > > const void *other_d_ptr = kp->dataPointers.value(ptr, 0); > if (Q_UNLIKELY(other_d_ptr)) { ># ifdef BACKTRACE_SUPPORTED > printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace); ># endif > qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked " > "by another QSharedPointer object %p", ptr, other_d_ptr); > } > > Data data; > data.pointer = ptr; ># ifdef BACKTRACE_SUPPORTED > data.backtrace = saveBacktrace(); ># endif > > kp->dPointers.insert(d_ptr, data); > kp->dataPointers.insert(ptr, d_ptr); > Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); >} > >/*! > \internal >*/ >void QtSharedPointer::internalSafetyCheckRemove(const void *d_ptr) >{ > KnownPointers *const kp = knownPointers(); > if (!kp) > return; // end-game: the application is being destroyed already > > QMutexLocker lock(&kp->mutex); > > const auto it = kp->dPointers.constFind(d_ptr); > if (Q_UNLIKELY(it == kp->dPointers.cend())) { > qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. " > "To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout " > "in your code.", d_ptr); > } > > const auto it2 = kp->dataPointers.constFind(it->pointer); > Q_ASSERT(it2 != kp->dataPointers.cend()); > > //qDebug("Removing d=%p value=%p", d_ptr, it->pointer); > > // remove entries > kp->dataPointers.erase(it2); > kp->dPointers.erase(it); > Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); >} > >/*! > \internal > Called by the QSharedPointer autotest >*/ >void QtSharedPointer::internalSafetyCheckCleanCheck() >{ ># ifdef QT_BUILD_INTERNAL > KnownPointers *const kp = knownPointers(); > Q_ASSERT_X(kp, "internalSafetyCheckSelfCheck()", "Called after global statics deletion!"); > > if (Q_UNLIKELY(kp->dPointers.size() != kp->dataPointers.size())) > qFatal("Internal consistency error: the number of pointers is not equal!"); > > if (Q_UNLIKELY(!kp->dPointers.isEmpty())) > qFatal("Pointer cleaning failed: %d entries remaining", kp->dPointers.size()); ># endif >} > >QT_END_NAMESPACE
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 671882
:
556252
|
556254
| 556256