summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorJędrzej Nowacki <jedrzej.nowacki@digia.com>2013-02-12 14:08:48 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-02-20 15:22:55 +0100
commitdacc222d5a3327fb27d69e57d99111cdf9084304 (patch)
treede03a59bba5f628b51fa03a4230b43c215da12ee /tests
parentd3a4230757931a704f36dd1eb4917a5ce61f80b4 (diff)
Fix QVector detaching in one thread while another destroys it.
The patch adds handling for a case when a QVector is shared between two threads. In such scenario detaching in one thread could collide with destruction in the other one, causing a memory leak or assert in debug mode. Task-number: QTBUG-29134 Change-Id: Idbff250d9cfc6cf83174954ea91dbf41f8ea4aa4 Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp78
1 files changed, 77 insertions, 1 deletions
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index c5ed44b952..7738a2c797 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -41,6 +41,8 @@
#include <QtTest/QtTest>
#include <QAtomicInt>
+#include <QThread>
+#include <QSemaphore>
#include <qvector.h>
struct Movable {
@@ -272,6 +274,9 @@ private slots:
void detachInt() const;
void detachMovable() const;
void detachCustom() const;
+ void detachThreadSafetyInt() const;
+ void detachThreadSafetyMovable() const;
+ void detachThreadSafetyCustom() const;
private:
template<typename T> void copyConstructor() const;
@@ -295,6 +300,7 @@ private:
template<typename T> void setSharable_data() const;
template<typename T> void setSharable() const;
template<typename T> void detach() const;
+ template<typename T> void detachThreadSafety() const;
};
@@ -2213,5 +2219,75 @@ void tst_QVector::detachCustom() const
QCOMPARE(instancesCount, Custom::counter.loadAcquire());
}
-QTEST_APPLESS_MAIN(tst_QVector)
+static QAtomicPointer<QVector<int> > detachThreadSafetyDataInt;
+static QAtomicPointer<QVector<Movable> > detachThreadSafetyDataMovable;
+static QAtomicPointer<QVector<Custom> > detachThreadSafetyDataCustom;
+
+template<typename T> QAtomicPointer<QVector<T> > *detachThreadSafetyData();
+template<> QAtomicPointer<QVector<int> > *detachThreadSafetyData() { return &detachThreadSafetyDataInt; }
+template<> QAtomicPointer<QVector<Movable> > *detachThreadSafetyData() { return &detachThreadSafetyDataMovable; }
+template<> QAtomicPointer<QVector<Custom> > *detachThreadSafetyData() { return &detachThreadSafetyDataCustom; }
+
+static QSemaphore detachThreadSafetyLock;
+
+template<typename T>
+void tst_QVector::detachThreadSafety() const
+{
+ delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(new QVector<T>(SimpleValue<T>::vector(400)));
+
+ static const uint threadsCount = 5;
+
+ struct : QThread {
+ void run() Q_DECL_OVERRIDE
+ {
+ QVector<T> copy(*detachThreadSafetyData<T>()->load());
+ QVERIFY(!copy.isDetached());
+ detachThreadSafetyLock.release();
+ detachThreadSafetyLock.acquire(100);
+ copy.detach();
+ }
+ } threads[threadsCount];
+
+ for (uint i = 0; i < threadsCount; ++i)
+ threads[i].start();
+ QThread::yieldCurrentThread();
+ detachThreadSafetyLock.acquire(threadsCount);
+
+ // destroy static original data
+ delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(0);
+
+ QVERIFY(threadsCount < 100);
+ detachThreadSafetyLock.release(threadsCount * 100);
+ QThread::yieldCurrentThread();
+
+ for (uint i = 0; i < threadsCount; ++i)
+ threads[i].wait();
+}
+
+void tst_QVector::detachThreadSafetyInt() const
+{
+ for (uint i = 0; i < 128; ++i)
+ detachThreadSafety<int>();
+}
+
+void tst_QVector::detachThreadSafetyMovable() const
+{
+ const int instancesCount = Movable::counter.loadAcquire();
+ for (uint i = 0; i < 128; ++i) {
+ detachThreadSafety<Movable>();
+ QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
+ }
+}
+
+void tst_QVector::detachThreadSafetyCustom() const
+{
+ const int instancesCount = Custom::counter.loadAcquire();
+ for (uint i = 0; i < 128; ++i) {
+ detachThreadSafety<Custom>();
+ QCOMPARE(Custom::counter.loadAcquire(), instancesCount);
+ }
+}
+
+
+QTEST_MAIN(tst_QVector)
#include "tst_qvector.moc"