diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-07-12 15:02:09 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2019-09-02 18:37:07 +0200 |
commit | c8d3eb35e73e650e73fcc47c78af6d86ff58bfd9 (patch) | |
tree | 1ed478548c7593476ea98faa8136567a66a7a60c /src | |
parent | 162e23d838101ddcd8e6416dd346465ac20bd05d (diff) |
Fixup move semantics of QColorSpace
Stop using QExplicitlySharedDataPointer, makes it possible to inline
the move constructor and assign operator.
Also protect other methods from nullptr d_ptr, and change the default
constructed value to also have a null d_ptr, to match the result after
a move.
Change-Id: I40928feef90cc956ef84d0516a77b0ee0f8986c7
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/painting/qcolorspace.cpp | 74 | ||||
-rw-r--r-- | src/gui/painting/qcolorspace.h | 14 | ||||
-rw-r--r-- | src/gui/painting/qcolorspace_p.h | 15 |
3 files changed, 66 insertions, 37 deletions
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp index 043a951521..86d0c57cfe 100644 --- a/src/gui/painting/qcolorspace.cpp +++ b/src/gui/painting/qcolorspace.cpp @@ -461,19 +461,19 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace Creates a new colorspace object that represents \a colorSpaceId. */ QColorSpace::QColorSpace(QColorSpace::ColorSpaceId colorSpaceId) -{ - static QExplicitlySharedDataPointer<QColorSpacePrivate> predefinedColorspacePrivates[QColorSpace::Bt2020]; - if (colorSpaceId <= QColorSpace::Unknown) { - if (!predefinedColorspacePrivates[0]) - predefinedColorspacePrivates[0] = new QColorSpacePrivate(QColorSpace::Undefined); - d_ptr = predefinedColorspacePrivates[0]; // unknown and undefined both returns the static undefined colorspace. - } else { - if (!predefinedColorspacePrivates[colorSpaceId - 1]) - predefinedColorspacePrivates[colorSpaceId - 1] = new QColorSpacePrivate(colorSpaceId); - d_ptr = predefinedColorspacePrivates[colorSpaceId - 1]; + : d_ptr(nullptr) +{ + static QColorSpacePrivate *predefinedColorspacePrivates[QColorSpace::Bt2020]; + // Unknown and undefined both returns the static undefined colorspace + if (colorSpaceId > QColorSpace::Unknown) { + if (!predefinedColorspacePrivates[colorSpaceId - 2]) { + predefinedColorspacePrivates[colorSpaceId - 2] = new QColorSpacePrivate(colorSpaceId); + predefinedColorspacePrivates[colorSpaceId - 2]->ref.ref(); + } + d_ptr = predefinedColorspacePrivates[colorSpaceId - 2]; + d_ptr->ref.ref(); + Q_ASSERT(isValid()); } - - Q_ASSERT(colorSpaceId == QColorSpace::Undefined || isValid()); } /*! @@ -483,6 +483,7 @@ QColorSpace::QColorSpace(QColorSpace::ColorSpaceId colorSpaceId) QColorSpace::QColorSpace(QColorSpace::Primaries primaries, QColorSpace::TransferFunction fun, float gamma) : d_ptr(new QColorSpacePrivate(primaries, fun, gamma)) { + d_ptr->ref.ref(); } /*! @@ -492,6 +493,7 @@ QColorSpace::QColorSpace(QColorSpace::Primaries primaries, QColorSpace::Transfer QColorSpace::QColorSpace(QColorSpace::Primaries primaries, float gamma) : d_ptr(new QColorSpacePrivate(primaries, TransferFunction::Gamma, gamma)) { + d_ptr->ref.ref(); } /*! @@ -505,35 +507,34 @@ QColorSpace::QColorSpace(const QPointF &whitePoint, const QPointF &redPoint, QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint); if (!primaries.areValid()) { qWarning() << "QColorSpace attempted constructed from invalid primaries:" << whitePoint << redPoint << greenPoint << bluePoint; - d_ptr = QColorSpace(QColorSpace::Undefined).d_ptr; + d_ptr = nullptr; return; } d_ptr = new QColorSpacePrivate(primaries, fun, gamma); + d_ptr->ref.ref(); } QColorSpace::~QColorSpace() { -} - -QColorSpace::QColorSpace(QColorSpace &&colorSpace) noexcept - : d_ptr(std::move(colorSpace.d_ptr)) -{ + if (d_ptr && !d_ptr->ref.deref()) + delete d_ptr; } QColorSpace::QColorSpace(const QColorSpace &colorSpace) : d_ptr(colorSpace.d_ptr) { -} - -QColorSpace &QColorSpace::operator=(QColorSpace &&colorSpace) noexcept -{ - d_ptr = std::move(colorSpace.d_ptr); - return *this; + if (d_ptr) + d_ptr->ref.ref(); } QColorSpace &QColorSpace::operator=(const QColorSpace &colorSpace) { + QColorSpacePrivate *oldD = d_ptr; d_ptr = colorSpace.d_ptr; + if (d_ptr) + d_ptr->ref.ref(); + if (oldD && !oldD->ref.deref()) + delete oldD; return *this; } @@ -549,6 +550,8 @@ QColorSpace &QColorSpace::operator=(const QColorSpace &colorSpace) */ QColorSpace::ColorSpaceId QColorSpace::colorSpaceId() const noexcept { + if (Q_UNLIKELY(!d_ptr)) + return QColorSpace::Undefined; return d_ptr->id; } @@ -571,6 +574,8 @@ QColorSpace::Primaries QColorSpace::primaries() const noexcept */ QColorSpace::TransferFunction QColorSpace::transferFunction() const noexcept { + if (Q_UNLIKELY(!d_ptr)) + return QColorSpace::TransferFunction::Custom; return d_ptr->transferFunction; } @@ -583,6 +588,8 @@ QColorSpace::TransferFunction QColorSpace::transferFunction() const noexcept */ float QColorSpace::gamma() const noexcept { + if (Q_UNLIKELY(!d_ptr)) + return 0.0f; return d_ptr->gamma; } @@ -599,7 +606,7 @@ void QColorSpace::setTransferFunction(QColorSpace::TransferFunction transferFunc return; if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma) return; - d_ptr.detach(); + QColorSpacePrivate::getWritable(*this); // detach d_ptr->description.clear(); d_ptr->transferFunction = transferFunction; d_ptr->gamma = gamma; @@ -637,7 +644,7 @@ void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId) return; if (d_ptr->primaries == primariesId) return; - d_ptr.detach(); + QColorSpacePrivate::getWritable(*this); // detach d_ptr->description.clear(); d_ptr->primaries = primariesId; d_ptr->identifyColorSpace(); @@ -663,7 +670,7 @@ void QColorSpace::setPrimaries(const QPointF &whitePoint, const QPointF &redPoin QColorMatrix toXyz = primaries.toXyzMatrix(); if (QColorVector(primaries.whitePoint) == d_ptr->whitePoint && toXyz == d_ptr->toXyz) return; - d_ptr.detach(); + QColorSpacePrivate::getWritable(*this); // detach d_ptr->description.clear(); d_ptr->primaries = QColorSpace::Primaries::Custom; d_ptr->toXyz = toXyz; @@ -685,6 +692,8 @@ void QColorSpace::setPrimaries(const QPointF &whitePoint, const QPointF &redPoin */ QByteArray QColorSpace::iccProfile() const { + if (Q_UNLIKELY(!d_ptr)) + return QByteArray(); if (!d_ptr->iccProfile.isEmpty()) return d_ptr->iccProfile; if (!isValid()) @@ -708,8 +717,9 @@ QColorSpace QColorSpace::fromIccProfile(const QByteArray &iccProfile) QColorSpace colorSpace; if (QIcc::fromIccProfile(iccProfile, &colorSpace)) return colorSpace; - colorSpace.d_ptr->id = QColorSpace::Undefined; - colorSpace.d_ptr->iccProfile = iccProfile; + QColorSpacePrivate *d = QColorSpacePrivate::getWritable(colorSpace); + d->id = QColorSpace::Undefined; + d->iccProfile = iccProfile; return colorSpace; } @@ -718,7 +728,7 @@ QColorSpace QColorSpace::fromIccProfile(const QByteArray &iccProfile) */ bool QColorSpace::isValid() const noexcept { - return d_ptr->id != QColorSpace::Undefined && d_ptr->toXyz.isValid() + return d_ptr && d_ptr->id != QColorSpace::Undefined && d_ptr->toXyz.isValid() && d_ptr->trc[0].isValid() && d_ptr->trc[1].isValid() && d_ptr->trc[2].isValid(); } @@ -731,6 +741,8 @@ bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2) { if (colorSpace1.d_ptr == colorSpace2.d_ptr) return true; + if (!colorSpace1.d_ptr || !colorSpace2.d_ptr) + return false; if (colorSpace1.colorSpaceId() == QColorSpace::Undefined && colorSpace2.colorSpaceId() == QColorSpace::Undefined) return colorSpace1.d_ptr->iccProfile == colorSpace2.d_ptr->iccProfile; @@ -780,7 +792,7 @@ QColorTransform QColorSpace::transformationToColorSpace(const QColorSpace &color if (!isValid() || !colorspace.isValid()) return QColorTransform(); - return d_ptr->transformationToColorSpace(colorspace.d_ptr.constData()); + return d_ptr->transformationToColorSpace(colorspace.d_ptr); } /***************************************************************************** diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h index a7c1091911..5941682bbb 100644 --- a/src/gui/painting/qcolorspace.h +++ b/src/gui/painting/qcolorspace.h @@ -90,11 +90,19 @@ public: TransferFunction fun, float gamma = 0.0f); ~QColorSpace(); - QColorSpace(QColorSpace &&colorSpace) noexcept; QColorSpace(const QColorSpace &colorSpace); - QColorSpace &operator=(QColorSpace &&colorSpace) noexcept; QColorSpace &operator=(const QColorSpace &colorSpace); + QColorSpace(QColorSpace &&colorSpace) noexcept + : d_ptr(qExchange(colorSpace.d_ptr, nullptr)) + { } + QColorSpace &operator=(QColorSpace &&colorSpace) noexcept + { + // Make the deallocation of this->d_ptr happen in ~QColorSpace() + QColorSpace(std::move(colorSpace)).swap(*this); + return *this; + } + void swap(QColorSpace &colorSpace) noexcept { qSwap(d_ptr, colorSpace.d_ptr); } @@ -123,7 +131,7 @@ public: private: Q_DECLARE_PRIVATE(QColorSpace) - QExplicitlySharedDataPointer<QColorSpacePrivate> d_ptr; + QColorSpacePrivate *d_ptr; }; bool Q_GUI_EXPORT operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2); diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h index 2a40a0cfd8..037111a0ae 100644 --- a/src/gui/painting/qcolorspace_p.h +++ b/src/gui/painting/qcolorspace_p.h @@ -95,15 +95,24 @@ public: QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrivate &other) = default; + // named different from get to avoid accidental detachs static QColorSpacePrivate *getWritable(QColorSpace &colorSpace) { - colorSpace.d_ptr.detach(); - return colorSpace.d_ptr.data(); + if (!colorSpace.d_ptr) { + colorSpace.d_ptr = new QColorSpacePrivate; + colorSpace.d_ptr->ref.ref(); + } else if (colorSpace.d_ptr->ref.loadRelaxed() != 1) { + colorSpace.d_ptr->ref.deref(); + colorSpace.d_ptr = new QColorSpacePrivate(*colorSpace.d_ptr); + colorSpace.d_ptr->ref.ref(); + } + Q_ASSERT(colorSpace.d_ptr->ref.loadRelaxed() == 1); + return colorSpace.d_ptr; } static const QColorSpacePrivate *get(const QColorSpace &colorSpace) { - return colorSpace.d_ptr.data(); + return colorSpace.d_ptr; } void initialize(); |