summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qsharedpointer.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 09:18:55 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 09:18:55 (GMT)
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/corelib/tools/qsharedpointer.cpp
downloadQt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2
Long live Qt 4.5!
Diffstat (limited to 'src/corelib/tools/qsharedpointer.cpp')
-rw-r--r--src/corelib/tools/qsharedpointer.cpp868
1 files changed, 868 insertions, 0 deletions
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
new file mode 100644
index 0000000..d8a9923
--- /dev/null
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -0,0 +1,868 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsharedpointer.h"
+
+// to be sure we aren't causing a namespace clash:
+#include "qshareddata.h"
+
+/*!
+ \class QSharedPointer
+ \brief The QSharedPointer class holds a strong reference to a shared pointer
+ \since 4.5
+
+ \reentrant
+ \ingroup misc
+
+ 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 same QSharedPointer or QWeakPointer 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
+ 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 behaves like QSharedDataPointer,
+ except that it only detaches if
+ QExplicitlySharedDataPointer::detach() is explicitly called.
+
+ Finally, QPointer holds a pointer to a QObject-derived object, but
+ it does so weakly. QPointer is similar, in that behaviour, to
+ QWeakPointer: it does not allow you to prevent the object from
+ being destroyed. All you can do is query whether it has been
+ destroyed or not.
+
+ \sa QSharedDataPointer, QWeakPointer
+*/
+
+/*!
+ \class QWeakPointer
+ \brief The QWeakPointer class holds a weak reference to a shared pointer
+ \since 4.5
+ \reentrant
+ \ingroup misc
+
+ 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.
+
+ To access the pointer that QWeakPointer is tracking, you
+ must first create a QSharedPointer object and verify if the pointer
+ is null or not.
+
+ \sa QSharedPointer
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer()
+
+ Creates a QSharedPointer that points to null (0).
+*/
+
+/*!
+ \fn QSharedPointer::~QSharedPointer()
+
+ Destroys this QSharedPointer object. If it is the last reference to
+ the pointer stored, this will delete the pointer as well.
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer(T *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.
+*/
+
+/*!
+ \fn QSharedPointer::QSharedPointer(T *ptr, Deleter deleter)
+
+ 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 \a deleter paramter specifies the custom deleter for this
+ object. The custom deleter is called when the strong reference
+ count drops to 0 instead of the operator delete(). This is useful,
+ for instance, for calling deleteLater() in 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
+
+ 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 QSharedPointer::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 QSharedPointer::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.
+*/
+
+/*!
+ \fn QSharedPointer &QSharedPointer::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 QSharedPointer &QSharedPointer::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 T *QSharedPointer::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 T &QSharedPointer::operator *() const
+
+ Provides access to the shared pointer's members.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn T *QSharedPointer::operator ->() const
+
+ Provides access to the shared pointer's members.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn bool QSharedPointer::isNull() const
+
+ Returns true if this object is holding a reference to a null
+ pointer.
+*/
+
+/*!
+ \fn QSharedPointer::operator bool() const
+
+ Returns 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 bool QSharedPointer::operator !() const
+
+ Returns true if this object is null. This function is suitable
+ for use in \tt if-constructs, like:
+
+ \code
+ if (!sharedptr) { ... }
+ \endcode
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QSharedPointer<X> QSharedPointer::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 QSharedPointer<X> QSharedPointer::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 QSharedPointer<X> QSharedPointer::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 QWeakPointer<T> QSharedPointer::toWeakRef() const
+
+ Returns a weak reference object that shares the pointer referenced
+ by this object.
+*/
+
+/*!
+ \fn void QSharedPointer::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 QWeakPointer::QWeakPointer()
+
+ Creates a QWeakPointer that points to nothing.
+*/
+
+/*!
+ \fn QWeakPointer::~QWeakPointer()
+
+ Destroys this QWeakPointer object. The pointer referenced
+ by this object will not be deleted.
+*/
+
+/*!
+ \fn QWeakPointer::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 QWeakPointer::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 QWeakPointer &QWeakPointer::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 QWeakPointer &QWeakPointer::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 bool QWeakPointer::isNull() const
+
+ Returns 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 QWeakPointer::operator bool() const
+
+ Returns 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 bool QWeakPointer::operator !() const
+
+ Returns 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 QSharedPointer<T> QWeakPointer::toStrongRef() const
+
+ Promotes this weak reference to a strong one and returns a
+ QSharedPointer object holding that reference.
+*/
+
+/*!
+ \fn void QWeakPointer::clear()
+
+ Clears this QWeakPointer object, dropping the reference that it
+ may have had to the pointer.
+*/
+
+/*!
+ \fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns 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 bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns 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 bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
+ \relates QSharedPointer
+
+ Returns 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 bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
+ \relates QSharedPointer
+
+ Returns 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 bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns 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 bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
+ \relates QSharedPointer
+
+ Returns 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 bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns 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 bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns 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 bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns 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 bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+ \relates QWeakPointer
+
+ Returns 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 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 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 QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &other)
+ \relates QSharedPointer
+
+ Returns a shared pointer to the pointer held by \a other, 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 QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &other)
+ \relates QSharedPointer
+ \relates QWeakPointer
+
+ Returns a shared pointer to the pointer held by \a other, 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 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 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 QSharedPointer<X> qSharedPointerConstCast(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 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 QSharedPointer<X> qSharedPointerConstCast(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 const_cast to succeed. The \tt const and
+ \tt volatile differences between \tt T and \tt X are ignored.
+
+ 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.
+
+ \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerDynamicCast()
+*/
+
+/*!
+ \fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other)
+ \relates QWeakPointer
+
+ Returns a weak 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.
+*/
+
+#include <qset.h>
+#include <qmutex.h>
+
+#if !defined(QT_NO_MEMBER_TEMPLATES)
+
+//# 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_MACX)
+# define BACKTRACE_SUPPORTED
+# endif
+# endif
+
+# if !defined(BACKTRACE_SUPPORTED)
+// Dummy implementation of the functions.
+// Using QHashDummyValue also means that the QHash below is actually a QSet
+typedef QT_PREPEND_NAMESPACE(QHashDummyValue) Backtrace;
+
+static inline Backtrace saveBacktrace() { return Backtrace(); }
+static inline void printBacktrace(Backtrace) { }
+
+# else
+# include <sys/types.h>
+# include <execinfo.h>
+# include <stdio.h>
+# include <unistd.h>
+# include <sys/wait.h>
+
+typedef QT_PREPEND_NAMESPACE(QByteArray) Backtrace;
+
+static inline Backtrace saveBacktrace() __attribute__((always_inline));
+static inline Backtrace saveBacktrace()
+{
+ static const int maxFrames = 32;
+
+ Backtrace 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(Backtrace 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);
+ }
+}
+# endif // BACKTRACE_SUPPORTED
+
+namespace {
+ QT_USE_NAMESPACE
+ class KnownPointers
+ {
+ public:
+ QMutex mutex;
+ QHash<void *, Backtrace> values;
+ };
+}
+
+Q_GLOBAL_STATIC(KnownPointers, knownPointers)
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckAdd(const volatile void *ptr)
+{
+ QMutexLocker lock(&knownPointers()->mutex);
+ void *actual = const_cast<void*>(ptr);
+ if (knownPointers()->values.contains(actual)) {
+ printBacktrace(knownPointers()->values.value(actual));
+ qFatal("QSharedPointerData: internal self-check failed: pointer %p was already tracked "
+ "by another QSharedPointerData object", actual);
+ }
+
+ knownPointers()->values.insert(actual, saveBacktrace());
+}
+
+/*!
+ \internal
+*/
+void QtSharedPointer::internalSafetyCheckRemove(const volatile void *ptr)
+{
+ QMutexLocker lock(&knownPointers()->mutex);
+ void *actual = const_cast<void*>(ptr);
+ knownPointers()->values.remove(actual);
+}
+
+QT_END_NAMESPACE
+
+#endif