summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-02 16:33:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-10 15:52:07 +0200
commitcd0b5bba9a1a76e03d4b9b5105c4d16d1e1dfd1e (patch)
tree853feeaf4c90ef746e60ff505d71c201bf0f9d21 /src/gui
parent1613eff15e77bae222110cc5cb4b8c541f8ea918 (diff)
Make the named QColorSpace constructor thread-safe
Avoid accessing the shared pointer table without using atomic. Cleans up the shared table on exit for leak tracking utilities. Pick-to: 5.15 Change-Id: Ia2d6d79dea1c8be02bae2d8111e290f49eedf409 Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/painting/qcolorspace.cpp29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 5ae071f480..5657a90b9b 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -46,6 +46,7 @@
#include "qcolortransform_p.h"
#include "qicc_p.h"
+#include <qatomic.h>
#include <qmath.h>
#include <qtransform.h>
@@ -55,6 +56,18 @@ QT_BEGIN_NAMESPACE
QBasicMutex QColorSpacePrivate::s_lutWriteLock;
+static QAtomicPointer<QColorSpacePrivate> s_predefinedColorspacePrivates[QColorSpace::ProPhotoRgb] = {};
+static void cleanupPredefinedColorspaces()
+{
+ for (QAtomicPointer<QColorSpacePrivate> &ptr : s_predefinedColorspacePrivates) {
+ QColorSpacePrivate *prv = ptr.fetchAndStoreAcquire(nullptr);
+ if (prv && !prv->ref.deref())
+ delete prv;
+ }
+}
+
+Q_DESTRUCTOR_FUNCTION(cleanupPredefinedColorspaces)
+
QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Primaries primaries)
{
switch (primaries) {
@@ -426,12 +439,18 @@ QColorSpace::QColorSpace(NamedColorSpace namedColorSpace)
qWarning() << "QColorSpace attempted constructed from invalid QColorSpace::NamedColorSpace: " << int(namedColorSpace);
return;
}
- static QColorSpacePrivate *predefinedColorspacePrivates[QColorSpace::ProPhotoRgb + 1];
- if (!predefinedColorspacePrivates[namedColorSpace]) {
- predefinedColorspacePrivates[namedColorSpace] = new QColorSpacePrivate(namedColorSpace);
- predefinedColorspacePrivates[namedColorSpace]->ref.ref();
+ // The defined namespaces start at 1:
+ auto &atomicRef = s_predefinedColorspacePrivates[static_cast<int>(namedColorSpace) - 1];
+ QColorSpacePrivate *cspriv = atomicRef.loadAcquire();
+ if (!cspriv) {
+ auto *tmp = new QColorSpacePrivate(namedColorSpace);
+ tmp->ref.ref();
+ if (atomicRef.testAndSetOrdered(nullptr, tmp, cspriv))
+ cspriv = tmp;
+ else
+ delete tmp;
}
- d_ptr = predefinedColorspacePrivates[namedColorSpace];
+ d_ptr = cspriv;
d_ptr->ref.ref();
Q_ASSERT(isValid());
}