Q(E)SDP(V2): fill the API gap left by take()
take() returns a pointer to the shared data object *without* decrementing the reference counter. The primary use case is adopting the object from a Q(E)SDP into a different reference counting mechanism. This is fine, but if we support the "extraction" part, we shall also support the "adoption" part. Also, the API for the shared data pointer classes should match. Add an adopting tag type and suitable constructors to the shared data pointer classes, and add take() to the classes lacking it. Drive by, apply qExchange to take()'s implementation. [ChangeLog][QtCore][QAdoptSharedDataTag] New class. It is now possible to adopt pointers to shared data into a QExplicitlySharedDataPointer or a QSharedDataPointer object without incrementing the object's reference counter. Change-Id: I62b8b005c1bfbe2add58566206fca27634bb7e70 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
7745b49b2d
commit
aa442e9450
@ -64,6 +64,20 @@ QT_BEGIN_NAMESPACE
|
||||
The parameter is ignored.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QAdoptSharedDataTag
|
||||
\inmodule QtCore
|
||||
\threadsafe
|
||||
\brief The QAdoptSharedDataTag is a helper tag class.
|
||||
\since 6.0
|
||||
|
||||
QAdoptSharedDataTag objects are used in QSharedDataPointer
|
||||
and QExplicitlySharedDataPointer to adopt a pointer to
|
||||
shared data.
|
||||
|
||||
See QSharedDataPointer and QExplicitlySharedDataPointer for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QSharedDataPointer
|
||||
\inmodule QtCore
|
||||
@ -302,6 +316,18 @@ QT_BEGIN_NAMESPACE
|
||||
Same as data(). This function is provided for STL compatibility.
|
||||
*/
|
||||
|
||||
/*! \fn template <class T> const T* QSharedDataPointer<T>::take()
|
||||
\since 6.0
|
||||
|
||||
Returns a pointer to the shared object, and resets \e this to be \nullptr.
|
||||
(That is, this function sets the \e{d pointer} of \e this to \nullptr.)
|
||||
|
||||
\note The reference count of the returned object will \b{not} be
|
||||
decremented. This function can be used together with the
|
||||
constructor that takes a QAdoptSharedDataTag tag object to transfer
|
||||
the shared data object without intervening atomic operations.
|
||||
*/
|
||||
|
||||
/*! \fn template <class T> const T* QSharedDataPointer<T>::constData() const
|
||||
Returns a const pointer to the shared data object.
|
||||
This function does \e not call detach().
|
||||
@ -365,6 +391,15 @@ QT_BEGIN_NAMESPACE
|
||||
\a data and increments \a{data}'s reference count.
|
||||
*/
|
||||
|
||||
/*! \fn template <class T> QSharedDataPointer<T>::QSharedDataPointer(T* data, QAdoptSharedDataTag)
|
||||
\since 6.0
|
||||
Constructs a QSharedDataPointer with \e{d pointer} set to
|
||||
\a data. \a data's reference counter is \b{not} incremented;
|
||||
this can be used to adopt pointers obtained from take().
|
||||
|
||||
\sa take()
|
||||
*/
|
||||
|
||||
/*! \fn template <class T> QSharedDataPointer<T>::QSharedDataPointer(const QSharedDataPointer<T>& o)
|
||||
Sets the \e{d pointer} of \e this to the \e{d pointer} in
|
||||
\a o and increments the reference count of the shared
|
||||
@ -615,7 +650,9 @@ QT_BEGIN_NAMESPACE
|
||||
(That is, this function sets the \e{d pointer} of \e this to \nullptr.)
|
||||
|
||||
\note The reference count of the returned object will \b{not} be
|
||||
decremented.
|
||||
decremented. This function can be used together with the
|
||||
constructor that takes a QAdoptSharedDataTag tag object to transfer
|
||||
the shared data object without intervening atomic operations.
|
||||
*/
|
||||
|
||||
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::operator bool () const
|
||||
|
@ -64,6 +64,8 @@ public:
|
||||
~QSharedData() = default;
|
||||
};
|
||||
|
||||
struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
|
||||
|
||||
template <typename T>
|
||||
class QSharedDataPointer
|
||||
{
|
||||
@ -83,12 +85,15 @@ public:
|
||||
const T *data() const noexcept { return d; }
|
||||
const T *get() const noexcept { return d; }
|
||||
const T *constData() const noexcept { return d; }
|
||||
T *take() noexcept { return qExchange(d, nullptr); }
|
||||
|
||||
QSharedDataPointer() noexcept : d(nullptr) { }
|
||||
~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
|
||||
|
||||
explicit QSharedDataPointer(T *data) noexcept : d(data)
|
||||
{ if (d) d->ref.ref(); }
|
||||
QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
|
||||
{}
|
||||
QSharedDataPointer(const QSharedDataPointer &o) noexcept : d(o.d)
|
||||
{ if (d) d->ref.ref(); }
|
||||
|
||||
@ -166,7 +171,7 @@ public:
|
||||
T *data() const noexcept { return d; }
|
||||
T *get() const noexcept { return d; }
|
||||
const T *constData() const noexcept { return d; }
|
||||
T *take() noexcept { T *x = d; d = nullptr; return x; }
|
||||
T *take() noexcept { return qExchange(d, nullptr); }
|
||||
|
||||
void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
|
||||
|
||||
@ -175,6 +180,8 @@ public:
|
||||
|
||||
explicit QExplicitlySharedDataPointer(T *data) noexcept : d(data)
|
||||
{ if (d) d->ref.ref(); }
|
||||
QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
|
||||
{}
|
||||
QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : d(o.d)
|
||||
{ if (d) d->ref.ref(); }
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#define QSHAREDDATA_IMPL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qshareddata.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -66,6 +67,11 @@ public:
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
QExplicitlySharedDataPointerV2(T *t, QAdoptSharedDataTag) noexcept
|
||||
: d(t)
|
||||
{
|
||||
}
|
||||
|
||||
QExplicitlySharedDataPointerV2(const QExplicitlySharedDataPointerV2 &other) noexcept
|
||||
: d(other.d)
|
||||
{
|
||||
@ -120,6 +126,11 @@ public:
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
constexpr T *take() noexcept
|
||||
{
|
||||
return qExchange(d, nullptr);
|
||||
}
|
||||
|
||||
bool isShared() const noexcept
|
||||
{
|
||||
return d && d->ref.loadRelaxed() != 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user