Deprecate the use of QWeakPointer to track QObjects.

The main problem with using QWeakPointer to track QObjects is that it
has API to convert to QSharedPointer, which is undefined behavior. There
is no need to overload the meaning of QWeakPointer with QObject
tracking.

QPointer is more suitable and should be used instead. Because QPointer
is implemented in terms of QWeakPointer, we need to add some overloads
which are not deprecated.

Change-Id: If0333e4800c9fd277629cc69185c9ca3e4e7e81d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Stephen Kelly 2012-05-25 10:31:03 +02:00 committed by Qt by Nokia
parent 77a03ebd8d
commit ee7fa67eb0
3 changed files with 28 additions and 52 deletions

View File

@ -57,7 +57,7 @@ class QPointerBase
protected: protected:
inline QPointerBase() : wp() { } inline QPointerBase() : wp() { }
inline QPointerBase(QObject *p) : wp(p) { } inline QPointerBase(QObject *p) : wp(p, true) { }
// compiler-generated copy/move ctor/assignment operators are fine! (even though public) // compiler-generated copy/move ctor/assignment operators are fine! (even though public)
inline ~QPointerBase() { } inline ~QPointerBase() { }
@ -65,7 +65,7 @@ protected:
{ return wp.data(); } { return wp.data(); }
inline void assign(QObject *p) inline void assign(QObject *p)
{ wp = p; } { wp.assign(p); }
inline bool isNull() const inline bool isNull() const
{ return wp.isNull(); } { return wp.isNull(); }

View File

@ -107,9 +107,8 @@
it makes no use of additional structure or reference counting. it makes no use of additional structure or reference counting.
Finally, QPointer holds a pointer to a QObject-derived object, but it Finally, QPointer holds a pointer to a QObject-derived object, but it
does so weakly. QPointer can be replaced by QWeakPointer in almost all does so weakly. QWeakPointer has the same functionality, but its use for
cases, since they have the same functionality. See that function is deprecated.
\l{QWeakPointer#tracking-qobject} for more information.
\section1 Optional pointer tracking \section1 Optional pointer tracking
@ -181,8 +180,7 @@
(see below for information on custom deleters). The strong reference (see below for information on custom deleters). The strong reference
count can also exceptionally be -1, indicating that there are no count can also exceptionally be -1, indicating that there are no
QSharedPointers attached to an object, which is tracked too. The only QSharedPointers attached to an object, which is tracked too. The only
case where this is possible is that of case where this is possible is that of QWeakPointers tracking a QObject.
\l{QWeakPointer#tracking-qobject}{QWeakPointers tracking a QObject}.
The weak reference count controls the lifetime of the d-pointer itself. The weak reference count controls the lifetime of the d-pointer itself.
It can be thought of as an internal/intrusive reference count for It can be thought of as an internal/intrusive reference count for
@ -369,8 +367,7 @@
deleted or not in another context. deleted or not in another context.
QWeakPointer objects can only be created by assignment from a QWeakPointer objects can only be created by assignment from a
QSharedPointer. The exception is pointers derived from QObject: in that QSharedPointer.
case, QWeakPointer serves as a replacement to QPointer.
It's important to note that QWeakPointer provides no automatic casting It's important to note that QWeakPointer provides no automatic casting
operators to prevent mistakes from happening. Even though QWeakPointer operators to prevent mistakes from happening. Even though QWeakPointer
@ -389,45 +386,6 @@
not get deleted (or if you only need the pointer value) and the cost of not get deleted (or if you only need the pointer value) and the cost of
creating a QSharedPointer using toStrongRef() is too high. creating a QSharedPointer using toStrongRef() is too high.
That function can also be used to obtain the tracked pointer for
QWeakPointers that cannot be promoted to QSharedPointer, such as those
created directly from a QObject pointer (not via QSharedPointer).
\section1 Tracking QObject
QWeakPointer can be used to track deletion of classes that derive from QObject,
even if they are not managed by QSharedPointer. When used in that role,
QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer
is also more efficient than QPointer, so it should be preferred in all
new code.
To do that, QWeakPointer provides a special constructor that is only
available if the template parameter \tt T is either QObject or a class
deriving from it. Trying to use that constructor if \tt T does not derive
from QObject will result in compilation errors.
To obtain the QObject being tracked by QWeakPointer, you must use the
QWeakPointer::data() function, but only if you can guarantee that the
object cannot get deleted by another context. It should be noted that
QPointer had the same constraint, so use of QWeakPointer forces you to
consider whether the pointer is still valid.
QObject-derived classes can only be deleted in the thread they have
affinity to (which is the thread they were created in or moved to, using
QObject::moveToThread()). In special, QWidget-derived classes cannot be
created in non-GUI threads nor moved there. Therefore, guaranteeing that
the tracked QObject has affinity to the current thread is enough to also
guarantee that it won't be deleted asynchronously.
Note that QWeakPointer's size and data layout do not match QPointer, so
it cannot replace that class in a binary-compatible manner.
Care must also be taken with QWeakPointers created directly from QObject
pointers when dealing with code that was compiled with Qt versions prior
to 4.6. Those versions may not track the reference counters correctly, so
QWeakPointers created from QObject should never be passed to code that
hasn't been recompiled.
\omit \omit
\secton1 QWeakPointer internals \secton1 QWeakPointer internals
@ -764,6 +722,7 @@
/*! /*!
\fn QWeakPointer::QWeakPointer(const QObject *obj) \fn QWeakPointer::QWeakPointer(const QObject *obj)
\since 4.6 \since 4.6
\deprecated
Creates a QWeakPointer that holds a weak reference directly to the Creates a QWeakPointer that holds a weak reference directly to the
QObject \a obj. This constructor is only available if the template type QObject \a obj. This constructor is only available if the template type
@ -776,18 +735,19 @@
Note that QWeakPointers created this way on arbitrary QObjects usually Note that QWeakPointers created this way on arbitrary QObjects usually
cannot be promoted to QSharedPointer. cannot be promoted to QSharedPointer.
\sa QSharedPointer, QWeakPointer#tracking-qobject \sa QSharedPointer, QPointer
*/ */
/*! /*!
\fn QWeakPointer &QWeakPointer::operator=(const QObject *obj) \fn QWeakPointer &QWeakPointer::operator=(const QObject *obj)
\since 4.6 \since 4.6
\deprecated
Makes this QWeakPointer hold a weak reference directly to the QObject Makes this QWeakPointer hold a weak reference directly to the QObject
\a obj. This function is only available if the template type \tt T is \a obj. This function is only available if the template type \tt T is
QObject or derives from it. QObject or derives from it.
\sa QWeakPointer#tracking-qobject \sa QPointer
*/ */
/*! /*!

View File

@ -585,13 +585,18 @@ public:
#ifndef QT_NO_QOBJECT #ifndef QT_NO_QOBJECT
// special constructor that is enabled only if X derives from QObject // special constructor that is enabled only if X derives from QObject
#if QT_DEPRECATED_SINCE(5, 0)
template <class X> template <class X>
inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr) QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr)
{ } { }
#endif #endif
#endif
#if QT_DEPRECATED_SINCE(5, 0)
template <class X> template <class X>
inline QWeakPointer &operator=(X *ptr) QT_DEPRECATED inline QWeakPointer &operator=(X *ptr)
{ return *this = QWeakPointer(ptr); } { return *this = QWeakPointer(ptr); }
#endif
inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value) inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value)
{ if (d) d->weakref.ref(); } { if (d) d->weakref.ref(); }
@ -664,6 +669,17 @@ private:
public: public:
#else #else
template <class X> friend class QSharedPointer; template <class X> friend class QSharedPointer;
friend class QPointerBase;
#endif
template <class X>
inline QWeakPointer &assign(X *ptr)
{ return *this = QWeakPointer<X>(ptr, true); }
#ifndef QT_NO_QOBJECT
template <class X>
inline QWeakPointer(X *ptr, bool) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr)
{ }
#endif #endif
inline void internalSet(Data *o, T *actual) inline void internalSet(Data *o, T *actual)