diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp index 42360a4caef..6db2a9adb9b 100644 --- a/src/corelib/tools/qshareddata.cpp +++ b/src/corelib/tools/qshareddata.cpp @@ -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 const T* QSharedDataPointer::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 const T* QSharedDataPointer::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 QSharedDataPointer::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 QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer& 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 QExplicitlySharedDataPointer::operator bool () const diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 669d9d14c40..bda117739c9 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -64,6 +64,8 @@ public: ~QSharedData() = default; }; +struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; }; + template 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(); } diff --git a/src/corelib/tools/qshareddata_impl.h b/src/corelib/tools/qshareddata_impl.h index 0a218b0b4b9..cf1c534cdf2 100644 --- a/src/corelib/tools/qshareddata_impl.h +++ b/src/corelib/tools/qshareddata_impl.h @@ -46,6 +46,7 @@ #define QSHAREDDATA_IMPL_H #include +#include 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;