summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/concurrent
diff options
context:
space:
mode:
authorHolger Ihrig <holger.ihrig@nokia.com>2011-08-24 10:51:34 +0200
committerHolger Ihrig <holger.ihrig@nokia.com>2011-08-30 13:17:07 +0200
commit0547598a28c3c1dd5c5f4c3ec9888b0de499199b (patch)
tree036c2f68f61cdef119cc74088ac8d4d60d608162 /tests/auto/corelib/concurrent
parentd610fbc13e589b36ce8f1e1af7166d215f0ccc90 (diff)
Moving relevant tests to corelib/concurrent
Adding tests for QFutureSynchronizer and QtConcurrentResultStore Added minor things in QFutureSynchronizer and QtConcurrentResultStore and removed tests for destruction Task-number: QTBUG-21066 Change-Id: I9f088b89463340f339c914bcb37fb2f9d3b62057 Reviewed-on: http://codereview.qt.nokia.com/3477 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Rohan McGovern <rohan.mcgovern@nokia.com> Reviewed-by: Jason McDonald <jason.mcdonald@nokia.com>
Diffstat (limited to 'tests/auto/corelib/concurrent')
-rw-r--r--tests/auto/corelib/concurrent/concurrent.pro19
-rw-r--r--tests/auto/corelib/concurrent/qfuture/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qfuture/qfuture.pro5
-rw-r--r--tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp1469
-rw-r--r--tests/auto/corelib/concurrent/qfuture/versioncheck.h49
-rw-r--r--tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro5
-rw-r--r--tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp158
-rw-r--r--tests/auto/corelib/concurrent/qfuturewatcher/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro4
-rw-r--r--tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp930
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro6
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp1546
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro5
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp360
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentmap/functions.h130
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro6
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp2448
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro5
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp491
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro5
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp518
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro5
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp536
-rw-r--r--tests/auto/corelib/concurrent/qthreadpool/.gitignore1
-rw-r--r--tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro4
-rw-r--r--tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp870
31 files changed, 9582 insertions, 0 deletions
diff --git a/tests/auto/corelib/concurrent/concurrent.pro b/tests/auto/corelib/concurrent/concurrent.pro
new file mode 100644
index 0000000000..6d7850b18f
--- /dev/null
+++ b/tests/auto/corelib/concurrent/concurrent.pro
@@ -0,0 +1,19 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qfuture \
+ qfuturesynchronizer \
+ qfuturewatcher \
+ qtconcurrentfilter \
+ qtconcurrentiteratekernel \
+ qtconcurrentmap \
+ qtconcurrentresultstore \
+ qtconcurrentrun \
+ qtconcurrentthreadengine \
+ qthreadpool
+
+symbian:SUBDIRS -= \
+ qtconcurrentfilter \
+ qtconcurrentiteratekernel \
+ qtconcurrentmap \
+ qtconcurrentrun \
+ qtconcurrentthreadengine \
diff --git a/tests/auto/corelib/concurrent/qfuture/.gitignore b/tests/auto/corelib/concurrent/qfuture/.gitignore
new file mode 100644
index 0000000000..77c055c874
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuture/.gitignore
@@ -0,0 +1 @@
+tst_qfuture
diff --git a/tests/auto/corelib/concurrent/qfuture/qfuture.pro b/tests/auto/corelib/concurrent/qfuture/qfuture.pro
new file mode 100644
index 0000000000..0e74f47678
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuture/qfuture.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+DEFINES += QT_STRICT_ITERATORS
+SOURCES += tst_qfuture.cpp
+QT = core core-private
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp b/tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp
new file mode 100644
index 0000000000..2178489bd9
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp
@@ -0,0 +1,1469 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QDebug>
+
+#define QFUTURE_TEST
+
+#include <QtTest/QtTest>
+#include <qfuture.h>
+#include "versioncheck.h"
+#include <qfuturewatcher.h>
+#include <qtconcurrentresultstore.h>
+#include <qtconcurrentexception.h>
+
+#ifndef QT_NO_CONCURRENT_TEST
+#include <private/qfutureinterface_p.h>
+
+using namespace QtConcurrent;
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QFuture: public QObject
+{
+ Q_OBJECT
+private slots:
+ void resultStore();
+ void future();
+ void futureInterface();
+ void refcounting();
+ void cancel();
+ void statePropagation();
+ void multipleResults();
+ void indexedResults();
+ void progress();
+ void progressText();
+ void resultsAfterFinished();
+ void resultsAsList();
+ void implicitConversions();
+ void iterators();
+ void pause();
+ void throttling();
+ void voidConversions();
+#ifndef QT_NO_EXCEPTIONS
+ void exceptions();
+ void exceptions_QTBUG18149();
+#endif
+};
+
+QTEST_MAIN(tst_QFuture)
+
+void tst_QFuture::resultStore()
+{
+ int int0 = 0;
+ int int1 = 1;
+ int int2 = 2;
+
+ {
+ ResultStore<int> store;
+ ResultIteratorBase it = store.begin();
+ QVERIFY(store.begin() == store.end());
+ QVERIFY(store.resultAt(0) == store.end());
+ QVERIFY(store.resultAt(1) == store.end());
+ }
+
+
+ {
+ ResultStoreBase store;
+ store.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since
+ store.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does.
+ ResultIteratorBase it = store.begin();
+ QCOMPARE(it.resultIndex(), 0);
+ QVERIFY(it == store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 1);
+ QVERIFY(it != store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QVERIFY(it != store.begin());
+ QVERIFY(it == store.end());
+ }
+
+ QVector<int> vec0 = QVector<int>() << 2 << 3;
+ QVector<int> vec1 = QVector<int>() << 4 << 5;
+
+ {
+ ResultStoreBase store;
+ store.addResults(-1, &vec0, 2, 2);
+ store.addResults(-1, &vec1, 2, 2);
+ ResultIteratorBase it = store.begin();
+ QCOMPARE(it.resultIndex(), 0);
+ QVERIFY(it == store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 1);
+ QVERIFY(it != store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 2);
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 3);
+
+ ++it;
+ QVERIFY(it == store.end());
+ }
+ {
+ ResultStoreBase store;
+ store.addResult(-1, &int0);
+ store.addResults(-1, &vec1, 2, 2);
+ store.addResult(-1, &int1);
+
+ ResultIteratorBase it = store.begin();
+ QCOMPARE(it.resultIndex(), 0);
+ QVERIFY(it == store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 1);
+ QVERIFY(it != store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 2);
+ QVERIFY(it != store.end());
+ ++it;
+ QCOMPARE(it.resultIndex(), 3);
+ QVERIFY(it != store.end());
+ ++it;
+ QVERIFY(it == store.end());
+
+ QCOMPARE(store.resultAt(0).resultIndex(), 0);
+ QCOMPARE(store.resultAt(1).resultIndex(), 1);
+ QCOMPARE(store.resultAt(2).resultIndex(), 2);
+ QCOMPARE(store.resultAt(3).resultIndex(), 3);
+ QCOMPARE(store.resultAt(4), store.end());
+ }
+ {
+ ResultStore<int> store;
+ store.addResult(-1, &int0);
+ store.addResults(-1, &vec0);
+ store.addResult(-1, &int1);
+
+ ResultIteratorBase it = store.begin();
+ QCOMPARE(it.resultIndex(), 0);
+ QVERIFY(it == store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 1);
+ QVERIFY(it != store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 2);
+ QVERIFY(it != store.end());
+ ++it;
+ QCOMPARE(it.resultIndex(), 3);
+ QVERIFY(it != store.end());
+ ++it;
+ QVERIFY(it == store.end());
+
+ QCOMPARE(store.resultAt(0).value(), int0);
+ QCOMPARE(store.resultAt(1).value(), vec0[0]);
+ QCOMPARE(store.resultAt(2).value(), vec0[1]);
+ QCOMPARE(store.resultAt(3).value(), int1);
+ }
+ {
+ ResultStore<int> store;
+ store.addResult(-1, &int0);
+ store.addResults(-1, &vec0);
+ store.addResult(200, &int1);
+
+ QCOMPARE(store.resultAt(0).value(), int0);
+ QCOMPARE(store.resultAt(1).value(), vec0[0]);
+ QCOMPARE(store.resultAt(2).value(), vec0[1]);
+ QCOMPARE(store.resultAt(200).value(), int1);
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResult(1, &int1);
+ store.addResult(0, &int0);
+ store.addResult(-1, &int2);
+
+ QCOMPARE(store.resultAt(0).value(), int0);
+ QCOMPARE(store.resultAt(1).value(), int1);
+ QCOMPARE(store.resultAt(2).value(), int2);
+ }
+
+ {
+ ResultStore<int> store;
+ QCOMPARE(store.contains(0), false);
+ QCOMPARE(store.contains(1), false);
+ QCOMPARE(store.contains(INT_MAX), false);
+ }
+
+ {
+ // Test filter mode, where "gaps" in the result array aren't allowed.
+ ResultStore<int> store;
+ store.setFilterMode(true);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.contains(0), true);
+
+ store.addResult(2, &int2); // add result at index 2
+ QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet.
+
+ store.addResult(1, &int1);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), true); // 2 should be visible now.
+
+ store.addResult(4, &int0);
+ store.addResult(5, &int0);
+ store.addResult(7, &int0);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(7), false);
+
+ store.addResult(3, &int0); // adding 3 makes 4 and 5 visible
+ QCOMPARE(store.contains(4), true);
+ QCOMPARE(store.contains(5), true);
+ QCOMPARE(store.contains(7), false);
+
+ store.addResult(6, &int0); // adding 6 makes 7 visible
+
+ QCOMPARE(store.contains(6), true);
+ QCOMPARE(store.contains(7), true);
+ QCOMPARE(store.contains(8), false);
+ }
+
+ {
+ // test canceled results
+ ResultStore<int> store;
+ store.setFilterMode(true);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.contains(0), true);
+
+ store.addResult(2, &int0);
+ QCOMPARE(store.contains(2), false);
+
+ store.addCanceledResult(1); // report no result at 1
+
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), true); // 2 gets renamed to 1
+ QCOMPARE(store.contains(2), false);
+
+ store.addResult(3, &int0);
+ QCOMPARE(store.contains(2), true); //3 gets renamed to 2
+
+ store.addResult(6, &int0);
+ store.addResult(7, &int0);
+ QCOMPARE(store.contains(3), false);
+
+ store.addCanceledResult(4);
+ store.addCanceledResult(5);
+
+ QCOMPARE(store.contains(3), true); //6 gets renamed to 3
+ QCOMPARE(store.contains(4), true); //7 gets renamed to 4
+
+ store.addResult(8, &int0);
+ QCOMPARE(store.contains(5), true); //8 gets renamed to 4
+
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+ }
+
+ {
+ // test addResult return value
+ ResultStore<int> store;
+ store.setFilterMode(true);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.count(), 1); // result 0 becomes available
+ QCOMPARE(store.contains(0), true);
+
+ store.addResult(2, &int0);
+ QCOMPARE(store.count(), 1);
+ QCOMPARE(store.contains(2), false);
+
+ store.addCanceledResult(1);
+ QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available
+
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), false);
+
+ store.addResult(3, &int0);
+ QCOMPARE(store.count(), 3);
+ QCOMPARE(store.contains(2), true);
+
+ store.addResult(6, &int0);
+ QCOMPARE(store.count(), 3);
+ store.addResult(7, &int0);
+ QCOMPARE(store.count(), 3);
+ QCOMPARE(store.contains(3), false);
+
+ store.addCanceledResult(4);
+ store.addCanceledResult(5);
+ QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available
+
+ QCOMPARE(store.contains(3), true);
+ QCOMPARE(store.contains(4), true);
+
+ store.addResult(8, &int0);
+ QCOMPARE(store.contains(5), true);
+ QCOMPARE(store.count(), 6);
+
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+ }
+
+ {
+ // test resultCount in non-filtered mode. It should always be possible
+ // to iterate through the results 0 to resultCount.
+ ResultStore<int> store;
+ store.addResult(0, &int0);
+
+ QCOMPARE(store.count(), 1);
+
+ store.addResult(2, &int0);
+
+ QCOMPARE(store.count(), 1);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.count(), 3);
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResult(2, &int0);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.count(), 3);
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResults(2, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.count(), 4);
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResults(2, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResults(0, &vec0);
+ QCOMPARE(store.count(), 4);
+ }
+ {
+ ResultStore<int> store;
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResults(0, &vec0);
+ QCOMPARE(store.count(), 2);
+
+ store.addResult(2, &int0);
+ QCOMPARE(store.count(), 5);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResults(0, &vec0);
+ QCOMPARE(store.count(), 2);
+
+ store.addCanceledResult(2);
+ QCOMPARE(store.count(), 4);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addCanceledResults(0, 3);
+ QCOMPARE(store.count(), 2);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addCanceledResults(0, 3);
+ QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1
+
+ store.addResult(5, &int0);
+ QCOMPARE(store.count(), 3);// result 5 becomes available at index 2
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResult(1, &int0);
+ store.addResult(3, &int0);
+ store.addResults(6, &vec0);
+ QCOMPARE(store.contains(0), false);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), false);
+ QCOMPARE(store.contains(3), true);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(6), true);
+ QCOMPARE(store.contains(7), true);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResult(1, &int0);
+ store.addResult(3, &int0);
+ store.addResults(6, &vec0);
+ QCOMPARE(store.contains(0), false);
+ QCOMPARE(store.contains(1), false);
+ QCOMPARE(store.contains(2), false);
+ QCOMPARE(store.contains(3), false);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+
+ store.addCanceledResult(0);
+ store.addCanceledResult(2);
+ store.addCanceledResults(4, 2);
+
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), true);
+ QCOMPARE(store.contains(3), true);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+ }
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addCanceledResult(0);
+ QCOMPARE(store.contains(0), false);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), false);
+ }
+}
+
+void tst_QFuture::future()
+{
+ // default constructors
+ QFuture<int> intFuture;
+ intFuture.waitForFinished();
+ QFuture<QString> stringFuture;
+ stringFuture.waitForFinished();
+ QFuture<void> voidFuture;
+ voidFuture.waitForFinished();
+ QFuture<void> defaultVoidFuture;
+ defaultVoidFuture.waitForFinished();
+
+ // copy constructor
+ QFuture<int> intFuture2(intFuture);
+ QFuture<void> voidFuture2(defaultVoidFuture);
+
+ // assigmnent operator
+ intFuture2 = QFuture<int>();
+ voidFuture2 = QFuture<void>();
+
+ // state
+ QCOMPARE(intFuture2.isStarted(), true);
+ QCOMPARE(intFuture2.isFinished(), true);
+}
+
+class IntResult : public QFutureInterface<int>
+{
+public:
+ QFuture<int> run()
+ {
+ this->reportStarted();
+ QFuture<int> future = QFuture<int>(this);
+
+ int res = 10;
+ reportFinished(&res);
+ return future;
+ }
+};
+
+int value = 10;
+
+class VoidResult : public QFutureInterfaceBase
+{
+public:
+ QFuture<void> run()
+ {
+ this->reportStarted();
+ QFuture<void> future = QFuture<void>(this);
+ reportFinished();
+ return future;
+ }
+};
+
+void tst_QFuture::futureInterface()
+{
+ {
+ QFuture<void> future;
+ {
+ QFutureInterface<void> i;
+ i.reportStarted();
+ future = i.future();
+ i.reportFinished();
+ }
+ }
+ {
+ QFuture<int> future;
+ {
+ QFutureInterface<int> i;
+ i.reportStarted();
+ i.reportResult(10);
+ future = i.future();
+ i.reportFinished();
+ }
+ QCOMPARE(future.resultAt(0), 10);
+ }
+
+ {
+ QFuture<int> intFuture;
+
+ QCOMPARE(intFuture.isStarted(), true);
+ QCOMPARE(intFuture.isFinished(), true);
+
+ IntResult result;
+
+ result.reportStarted();
+ intFuture = result.future();
+
+ QCOMPARE(intFuture.isStarted(), true);
+ QCOMPARE(intFuture.isFinished(), false);
+
+ result.reportFinished(&value);
+
+ QCOMPARE(intFuture.isStarted(), true);
+ QCOMPARE(intFuture.isFinished(), true);
+
+ int e = intFuture.result();
+
+ QCOMPARE(intFuture.isStarted(), true);
+ QCOMPARE(intFuture.isFinished(), true);
+ QCOMPARE(intFuture.isCanceled(), false);
+
+ QCOMPARE(e, value);
+ intFuture.waitForFinished();
+
+ IntResult intAlgo;
+ intFuture = intAlgo.run();
+ QFuture<int> intFuture2(intFuture);
+ QCOMPARE(intFuture.result(), value);
+ QCOMPARE(intFuture2.result(), value);
+ intFuture.waitForFinished();
+
+ VoidResult a;
+ a.run().waitForFinished();
+ }
+}
+
+template <typename T>
+void testRefCounting()
+{
+ QFutureInterface<T> interface;
+ QCOMPARE(int(interface.d->refCount), 1);
+
+ {
+ interface.reportStarted();
+
+ QFuture<T> f = interface.future();
+ QCOMPARE(int(interface.d->refCount), 2);
+
+ QFuture<T> f2(f);
+ QCOMPARE(int(interface.d->refCount), 3);
+
+ QFuture<T> f3;
+ f3 = f2;
+ QCOMPARE(int(interface.d->refCount), 4);
+
+ interface.reportFinished(0);
+ QCOMPARE(int(interface.d->refCount), 4);
+ }
+
+ QCOMPARE(int(interface.d->refCount), 1);
+}
+
+void tst_QFuture::refcounting()
+{
+ testRefCounting<int>();
+}
+
+void tst_QFuture::cancel()
+{
+ {
+ QFuture<void> f;
+ QFutureInterface<void> result;
+
+ result.reportStarted();
+ f = result.future();
+ QVERIFY(f.isCanceled() == false);
+ result.reportCanceled();
+ QVERIFY(f.isCanceled());
+ result.reportFinished();
+ QVERIFY(f.isCanceled());
+ f.waitForFinished();
+ QVERIFY(f.isCanceled());
+ }
+
+ // Cancel from the QFuture side and test if the result
+ // interface detects it.
+ {
+ QFutureInterface<void> result;
+
+ QFuture<void> f;
+ QVERIFY(f.isStarted() == true);
+
+ result.reportStarted();
+ f = result.future();
+
+ QVERIFY(f.isStarted() == true);
+
+ QVERIFY(result.isCanceled() == false);
+ f.cancel();
+
+ QVERIFY(result.isCanceled());
+
+ result.reportFinished();
+ }
+
+ // Test that finished futures can be canceled.
+ {
+ QFutureInterface<void> result;
+
+ QFuture<void> f;
+ QVERIFY(f.isStarted() == true);
+
+ result.reportStarted();
+ f = result.future();
+
+ QVERIFY(f.isStarted() == true);
+
+ result.reportFinished();
+
+ f.cancel();
+
+ QVERIFY(result.isCanceled());
+ QVERIFY(f.isCanceled());
+ }
+
+ // Results reported after canceled is called should not be propagated.
+ {
+
+ QFutureInterface<int> futureInterface;
+ futureInterface.reportStarted();
+ QFuture<int> f = futureInterface.future();
+
+ int result = 0;
+ futureInterface.reportResult(&result);
+ result = 1;
+ futureInterface.reportResult(&result);
+ f.cancel();
+ result = 2;
+ futureInterface.reportResult(&result);
+ result = 3;
+ futureInterface.reportResult(&result);
+ futureInterface.reportFinished();
+ QCOMPARE(f.results(), QList<int>());
+ }
+}
+
+void tst_QFuture::statePropagation()
+{
+ QFuture<void> f1;
+ QFuture<void> f2;
+
+ QCOMPARE(f1.isStarted(), true);
+
+ QFutureInterface<void> result;
+ result.reportStarted();
+ f1 = result.future();
+
+ f2 = f1;
+
+ QCOMPARE(f2.isStarted(), true);
+
+ result.reportCanceled();
+
+ QCOMPARE(f2.isStarted(), true);
+ QCOMPARE(f2.isCanceled(), true);
+
+ QFuture<void> f3 = f2;
+
+ QCOMPARE(f3.isStarted(), true);
+ QCOMPARE(f3.isCanceled(), true);
+
+ result.reportFinished();
+
+ QCOMPARE(f2.isStarted(), true);
+ QCOMPARE(f2.isCanceled(), true);
+
+ QCOMPARE(f3.isStarted(), true);
+ QCOMPARE(f3.isCanceled(), true);
+}
+
+/*
+ Tests that a QFuture can return multiple results.
+*/
+void tst_QFuture::multipleResults()
+{
+ IntResult a;
+ a.reportStarted();
+ QFuture<int> f = a.future();
+
+ QFuture<int> copy = f;
+ int result;
+
+ result = 1;
+ a.reportResult(&result);
+ QCOMPARE(f.resultAt(0), 1);
+
+ result = 2;
+ a.reportResult(&result);
+ QCOMPARE(f.resultAt(1), 2);
+
+ result = 3;
+ a.reportResult(&result);
+
+ result = 4;
+ a.reportFinished(&result);
+
+ QCOMPARE(f.results(), QList<int>() << 1 << 2 << 3 << 4);
+
+ // test foreach
+ QList<int> fasit = QList<int>() << 1 << 2 << 3 << 4;
+ {
+ QList<int> results;
+ foreach(int result, f)
+ results.append(result);
+ QCOMPARE(results, fasit);
+ }
+ {
+ QList<int> results;
+ foreach(int result, copy)
+ results.append(result);
+ QCOMPARE(results, fasit);
+ }
+}
+
+/*
+ Test out-of-order result reporting using indexes
+*/
+void tst_QFuture::indexedResults()
+{
+ {
+ QFutureInterface<QChar> Interface;
+ QFuture<QChar> f;
+ QVERIFY(f.isStarted() == true);
+
+ Interface.reportStarted();
+ f = Interface.future();
+
+ QVERIFY(f.isStarted() == true);
+
+ QChar result;
+
+ result = 'B';
+ Interface.reportResult(&result, 1);
+
+ QCOMPARE(f.resultAt(1), result);
+
+ result = 'A';
+ Interface.reportResult(&result, 0);
+ QCOMPARE(f.resultAt(0), result);
+
+ result = 'C';
+ Interface.reportResult(&result); // no index
+ QCOMPARE(f.resultAt(2), result);
+
+ Interface.reportFinished();
+
+ QCOMPARE(f.results(), QList<QChar>() << 'A' << 'B' << 'C');
+ }
+
+ {
+ // Test result reporting with a missing result in the middle
+ QFutureInterface<int> Interface;
+ Interface.reportStarted();
+ QFuture<int> f = Interface.future();
+ int result;
+
+ result = 0;
+ Interface.reportResult(&result, 0);
+ QVERIFY(f.isResultReadyAt(0));
+ QCOMPARE(f.resultAt(0), 0);
+
+ result = 3;
+ Interface.reportResult(&result, 3);
+ QVERIFY(f.isResultReadyAt(3));
+ QCOMPARE(f.resultAt(3), 3);
+
+ result = 2;
+ Interface.reportResult(&result, 2);
+ QVERIFY(f.isResultReadyAt(2));
+ QCOMPARE(f.resultAt(2), 2);
+
+ result = 4;
+ Interface.reportResult(&result); // no index
+ QVERIFY(f.isResultReadyAt(4));
+ QCOMPARE(f.resultAt(4), 4);
+
+ Interface.reportFinished();
+
+ QCOMPARE(f.results(), QList<int>() << 0 << 2 << 3 << 4);
+ }
+}
+
+void tst_QFuture::progress()
+{
+ QFutureInterface<QChar> result;
+ QFuture<QChar> f;
+
+ QCOMPARE (f.progressValue(), 0);
+
+ result.reportStarted();
+ f = result.future();
+
+ QCOMPARE (f.progressValue(), 0);
+
+ result.setProgressValue(50);
+
+ QCOMPARE (f.progressValue(), 50);
+
+ result.reportFinished();
+
+ QCOMPARE (f.progressValue(), 50);
+}
+
+void tst_QFuture::progressText()
+{
+ QFutureInterface<void> i;
+ i.reportStarted();
+ QFuture<void> f = i.future();
+
+ QCOMPARE(f.progressText(), QLatin1String(""));
+ i.setProgressValueAndText(1, QLatin1String("foo"));
+ QCOMPARE(f.progressText(), QLatin1String("foo"));
+ i.reportFinished();
+}
+
+/*
+ Test that results reported after finished are ignored.
+*/
+void tst_QFuture::resultsAfterFinished()
+{
+ {
+ IntResult a;
+ a.reportStarted();
+ QFuture<int> f = a.future();
+ int result;
+
+ QCOMPARE(f.resultCount(), 0);
+
+ result = 1;
+ a.reportResult(&result);
+ QCOMPARE(f.resultAt(0), 1);
+
+ a.reportFinished();
+
+ QCOMPARE(f.resultAt(0), 1);
+ QCOMPARE(f.resultCount(), 1);
+ result = 2;
+ a.reportResult(&result);
+ QCOMPARE(f.resultCount(), 1);
+ }
+ // cancel it
+ {
+ IntResult a;
+ a.reportStarted();
+ QFuture<int> f = a.future();
+ int result;
+
+ QCOMPARE(f.resultCount(), 0);
+
+ result = 1;
+ a.reportResult(&result);
+ QCOMPARE(f.resultAt(0), 1);
+ QCOMPARE(f.resultCount(), 1);
+
+ a.reportCanceled();
+
+ QCOMPARE(f.resultAt(0), 1);
+ QCOMPARE(f.resultCount(), 1);
+
+ result = 2;
+ a.reportResult(&result);
+ a.reportFinished();
+ }
+}
+
+void tst_QFuture::resultsAsList()
+{
+ IntResult a;
+ a.reportStarted();
+ QFuture<int> f = a.future();
+
+ int result;
+ result = 1;
+ a.reportResult(&result);
+ result = 2;
+ a.reportResult(&result);
+
+ a.reportFinished();
+
+ QList<int> results = f.results();
+ QCOMPARE(results, QList<int>() << 1 << 2);
+}
+
+/*
+ Test that QFuture<T> can be implicitly converted to T
+*/
+void tst_QFuture::implicitConversions()
+{
+ QFutureInterface<QString> iface;
+ iface.reportStarted();
+
+ QFuture<QString> f(&iface);
+
+ const QString input("FooBar 2000");
+ iface.reportFinished(&input);
+
+ const QString result = f;
+ QCOMPARE(result, input);
+ QCOMPARE(QString(f), input);
+ QCOMPARE(static_cast<QString>(f), input);
+}
+
+void tst_QFuture::iterators()
+{
+ {
+ QFutureInterface<int> e;
+ e.reportStarted();
+ QFuture<int> f = e.future();
+
+ int result;
+ result = 1;
+ e.reportResult(&result);
+ result = 2;
+ e.reportResult(&result);
+ result = 3;
+ e.reportResult(&result);
+ e.reportFinished();
+
+ QList<int> results;
+ QFutureIterator<int> i(f);
+ while (i.hasNext()) {
+ results.append(i.next());
+ }
+
+ QCOMPARE(results, f.results());
+
+ QFuture<int>::const_iterator i1 = f.begin(), i2 = i1 + 1;
+ QFuture<int>::const_iterator c1 = i1, c2 = c1 + 1;
+
+ QVERIFY(i1 == i1);
+ QVERIFY(i1 == c1);
+ QVERIFY(c1 == i1);
+ QVERIFY(c1 == c1);
+ QVERIFY(i2 == i2);
+ QVERIFY(i2 == c2);
+ QVERIFY(c2 == i2);
+ QVERIFY(c2 == c2);
+
+ QVERIFY(i1 != i2);
+ QVERIFY(i1 != c2);
+ QVERIFY(c1 != i2);
+ QVERIFY(c1 != c2);
+ QVERIFY(i2 != i1);
+ QVERIFY(i2 != c1);
+ QVERIFY(c2 != i1);
+ QVERIFY(c2 != c1);
+
+ int x1 = *i1;
+ Q_UNUSED(x1);
+ int x2 = *i2;
+ Q_UNUSED(x2);
+ int y1 = *c1;
+ Q_UNUSED(y1);
+ int y2 = *c2;
+ Q_UNUSED(y2);
+ }
+
+ {
+ QFutureInterface<QString> e;
+ e.reportStarted();
+ QFuture<QString> f = e.future();
+
+ e.reportResult(QString("one"));
+ e.reportResult(QString("two"));
+ e.reportResult(QString("three"));
+ e.reportFinished();
+
+ QList<QString> results;
+ QFutureIterator<QString> i(f);
+ while (i.hasNext()) {
+ results.append(i.next());
+ }
+
+ QCOMPARE(results, f.results());
+
+ QFuture<QString>::const_iterator i1 = f.begin(), i2 = i1 + 1;
+ QFuture<QString>::const_iterator c1 = i1, c2 = c1 + 1;
+
+ QVERIFY(i1 == i1);
+ QVERIFY(i1 == c1);
+ QVERIFY(c1 == i1);
+ QVERIFY(c1 == c1);
+ QVERIFY(i2 == i2);
+ QVERIFY(i2 == c2);
+ QVERIFY(c2 == i2);
+ QVERIFY(c2 == c2);
+
+ QVERIFY(i1 != i2);
+ QVERIFY(i1 != c2);
+ QVERIFY(c1 != i2);
+ QVERIFY(c1 != c2);
+ QVERIFY(i2 != i1);
+ QVERIFY(i2 != c1);
+ QVERIFY(c2 != i1);
+ QVERIFY(c2 != c1);
+
+ QString x1 = *i1;
+ QString x2 = *i2;
+ QString y1 = *c1;
+ QString y2 = *c2;
+
+ QCOMPARE(x1, y1);
+ QCOMPARE(x2, y2);
+
+ int i1Size = i1->size();
+ int i2Size = i2->size();
+ int c1Size = c1->size();
+ int c2Size = c2->size();
+
+ QCOMPARE(i1Size, c1Size);
+ QCOMPARE(i2Size, c2Size);
+ }
+
+ {
+ const int resultCount = 20;
+
+ QFutureInterface<int> e;
+ e.reportStarted();
+ QFuture<int> f = e.future();
+
+ for (int i = 0; i < resultCount; ++i) {
+ e.reportResult(i);
+ }
+
+ e.reportFinished();
+
+ {
+ QFutureIterator<int> it(f);
+ QFutureIterator<int> it2(it);
+ }
+
+ {
+ QFutureIterator<int> it(f);
+
+ for (int i = 0; i < resultCount - 1; ++i) {
+ QVERIFY(it.hasNext());
+ QCOMPARE(it.peekNext(), i);
+ QCOMPARE(it.next(), i);
+ }
+
+ QVERIFY(it.hasNext());
+ QCOMPARE(it.peekNext(), resultCount - 1);
+ QCOMPARE(it.next(), resultCount - 1);
+ QVERIFY(it.hasNext() == false);
+ }
+
+ {
+ QFutureIterator<int> it(f);
+ QVERIFY(it.hasNext());
+ it.toBack();
+ QVERIFY(it.hasNext() == false);
+ it.toFront();
+ QVERIFY(it.hasNext());
+ }
+ }
+}
+
+class SignalSlotObject : public QObject
+{
+Q_OBJECT
+public:
+ SignalSlotObject()
+ : finishedCalled(false),
+ canceledCalled(false),
+ rangeBegin(0),
+ rangeEnd(0) { }
+
+public slots:
+ void finished()
+ {
+// qDebug() << "finished called";
+ finishedCalled = true;
+ }
+
+ void canceled()
+ {
+// qDebug() << "canceled called";
+ canceledCalled = true;
+ }
+
+ void resultReady(int index)
+ {
+// qDebug() << "result" << index << "ready";
+ results.insert(index);
+ }
+
+ void progressRange(int begin, int end)
+ {
+// qDebug() << "progress range" << begin << end;
+ rangeBegin = begin;
+ rangeEnd = end;
+ }
+
+ void progress(int progress)
+ {
+// qDebug() << "progress" << progress;
+ reportedProgress.insert(progress);
+ }
+public:
+ bool finishedCalled;
+ bool canceledCalled;
+ QSet<int> results;
+ int rangeBegin;
+ int rangeEnd;
+ QSet<int> reportedProgress;
+};
+
+void tst_QFuture::pause()
+{
+ QFutureInterface<void> Interface;
+
+ Interface.reportStarted();
+ QFuture<void> f = Interface.future();
+
+ QVERIFY(Interface.isPaused() == false);
+ f.pause();
+ QVERIFY(Interface.isPaused() == true);
+ f.resume();
+ QVERIFY(Interface.isPaused() == false);
+ f.togglePaused();
+ QVERIFY(Interface.isPaused() == true);
+ f.togglePaused();
+ QVERIFY(Interface.isPaused() == false);
+
+ Interface.reportFinished();
+}
+
+const int resultCount = 1000;
+
+class ResultObject : public QObject
+{
+Q_OBJECT
+public slots:
+ void resultReady(int)
+ {
+
+ }
+public:
+};
+
+// Test that that the isPaused() on future result interface returns true
+// if we report a lot of results that are not handled.
+void tst_QFuture::throttling()
+{
+ {
+ QFutureInterface<void> i;
+
+ i.reportStarted();
+ QFuture<void> f = i.future();
+
+ QVERIFY(i.isThrottled() == false);
+
+ i.setThrottled(true);
+ QVERIFY(i.isThrottled());
+
+ i.setThrottled(false);
+ QVERIFY(i.isThrottled() == false);
+
+ i.setThrottled(true);
+ QVERIFY(i.isThrottled());
+
+ i.reportFinished();
+ }
+/*
+ QFutureInterface<int> *Interface = new QFutureInterface<int>();
+ Interface.reportStarted();
+ QFuture<int> f = QFuture<int>(Interface);
+
+ ResultObject object;
+ f.connectTo(ThrottledResultReadyAtSignal, &object, SLOT(resultReady(int)), Qt::DirectConnection);
+
+ for (int i = 0; i < 100; ++i)
+ Interface.reportResult(&i);
+
+ QVERIFY(Interface.isPaused() == true);
+
+ // read the results, this should resume the task.
+ for (int i = 0; i < 100; ++i)
+ f.throttledResult(i);
+
+ QVERIFY(Interface.isPaused() == false);
+ Interface.reportFinished();
+*/
+}
+
+void tst_QFuture::voidConversions()
+{
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+
+ QFuture<int> intFuture(&iface);
+
+ int value = 10;
+ iface.reportFinished(&value);
+
+ QFuture<void> voidFuture(intFuture);
+ voidFuture = intFuture;
+
+ QVERIFY(voidFuture == intFuture);
+}
+
+
+#ifndef QT_NO_EXCEPTIONS
+
+QFuture<void> createExceptionFuture()
+{
+ QFutureInterface<void> i;
+ i.reportStarted();
+ QFuture<void> f = i.future();
+
+ Exception e;
+ i.reportException(e);
+ i.reportFinished();
+ return f;
+}
+
+QFuture<int> createExceptionResultFuture()
+{
+ QFutureInterface<int> i;
+ i.reportStarted();
+ QFuture<int> f = i.future();
+ int r = 0;
+ i.reportResult(r);
+
+ Exception e;
+ i.reportException(e);
+ i.reportFinished();
+ return f;
+}
+
+class DerivedException : public Exception
+{
+public:
+ void raise() const { throw *this; }
+ Exception *clone() const { return new DerivedException(*this); }
+};
+
+QFuture<void> createDerivedExceptionFuture()
+{
+ QFutureInterface<void> i;
+ i.reportStarted();
+ QFuture<void> f = i.future();
+
+ DerivedException e;
+ i.reportException(e);
+ i.reportFinished();
+ return f;
+}
+
+void tst_QFuture::exceptions()
+{
+
+// test throwing from waitForFinished
+{
+ QFuture<void> f = createExceptionFuture();
+ bool caught = false;
+ try {
+ f.waitForFinished();
+ } catch (Exception &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+}
+
+// test result()
+{
+ QFuture<int> f = createExceptionResultFuture();
+ bool caught = false;
+ try {
+ f.result();
+ } catch (Exception &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+}
+
+// test result() and destroy
+{
+ bool caught = false;
+ try {
+ createExceptionResultFuture().result();
+ } catch (Exception &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+}
+
+// test results()
+{
+ QFuture<int> f = createExceptionResultFuture();
+ bool caught = false;
+ try {
+ f.results();
+ } catch (Exception &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+}
+
+// test foreach
+{
+ QFuture<int> f = createExceptionResultFuture();
+ bool caught = false;
+ try {
+ foreach (int e, f.results()) {
+ Q_UNUSED(e);
+ QFAIL("did not get exception");
+ }
+ } catch (Exception &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+}
+
+// catch derived exceptions
+{
+ bool caught = false;
+ try {
+ createDerivedExceptionFuture().waitForFinished();
+ } catch (Exception &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+}
+
+{
+ bool caught = false;
+ try {
+ createDerivedExceptionFuture().waitForFinished();
+ } catch (DerivedException &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+}
+
+}
+
+
+void tst_QFuture::exceptions_QTBUG18149()
+{
+ class MyClass
+ {
+ public:
+ ~MyClass()
+ {
+ QFuture<void> f = createExceptionFuture();
+ bool caught = false;
+ try {
+ f.waitForFinished();
+ } catch (Exception &) {
+ caught = true;
+ }
+ QVERIFY(caught);
+ }
+ };
+
+ try {
+ MyClass m;
+ Q_UNUSED(m);
+ throw 0;
+ } catch (int) {}
+
+}
+
+
+#endif // QT_NO_EXCEPTIONS
+
+#include "tst_qfuture.moc"
+
+#else
+QTEST_NOOP_MAIN
+#endif
diff --git a/tests/auto/corelib/concurrent/qfuture/versioncheck.h b/tests/auto/corelib/concurrent/qfuture/versioncheck.h
new file mode 100644
index 0000000000..9e4d0c6eeb
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuture/versioncheck.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qglobal.h>
+
+#ifdef QT_NO_CONCURRENT
+#define QT_NO_CONCURRENT_TEST
+#endif
+
+#if defined(Q_CC_MSVC) && _MSC_VER < 1400
+#define QT_NO_CONCURRENT_TEST
+#endif
diff --git a/tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro b/tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro
new file mode 100644
index 0000000000..11012cce24
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT = core
+SOURCES += tst_qfuturesynchronizer.cpp \
+
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp b/tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp
new file mode 100644
index 0000000000..5aced3f8c1
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+
+#include <QtCore/qfuturesynchronizer.h>
+#include <QtCore/qfuture.h>
+
+class tst_QFutureSynchronizer : public QObject
+{
+ Q_OBJECT
+
+
+private Q_SLOTS:
+ void construction();
+ void addFuture();
+ void cancelOnWait();
+ void clearFutures();
+ void futures();
+ void setFuture();
+ void waitForFinished();
+};
+
+
+void tst_QFutureSynchronizer::construction()
+{
+
+ QFuture<void> future;
+ QFutureSynchronizer<void> synchronizer;
+ QFutureSynchronizer<void> synchronizerWithFuture(future);
+
+ QCOMPARE(synchronizer.futures().size(), 0);
+ QCOMPARE(synchronizerWithFuture.futures().size(), 1);
+}
+
+void tst_QFutureSynchronizer::addFuture()
+{
+ QFutureSynchronizer<void> synchronizer;
+
+ synchronizer.addFuture(QFuture<void>());
+ QFuture<void> future;
+ synchronizer.addFuture(future);
+ synchronizer.addFuture(future);
+
+ QCOMPARE(synchronizer.futures().size(), 3);
+}
+
+void tst_QFutureSynchronizer::cancelOnWait()
+{
+ QFutureSynchronizer<void> synchronizer;
+ QVERIFY(!synchronizer.cancelOnWait());
+ synchronizer.setCancelOnWait(true);
+ QVERIFY(synchronizer.cancelOnWait());
+ synchronizer.setCancelOnWait(false);
+ QVERIFY(!synchronizer.cancelOnWait());
+ synchronizer.setCancelOnWait(true);
+ QVERIFY(synchronizer.cancelOnWait());
+}
+
+void tst_QFutureSynchronizer::clearFutures()
+{
+ QFutureSynchronizer<void> synchronizer;
+ synchronizer.clearFutures();
+ QVERIFY(synchronizer.futures().isEmpty());
+
+ synchronizer.addFuture(QFuture<void>());
+ QFuture<void> future;
+ synchronizer.addFuture(future);
+ synchronizer.addFuture(future);
+ synchronizer.clearFutures();
+ QVERIFY(synchronizer.futures().isEmpty());
+}
+
+void tst_QFutureSynchronizer::futures()
+{
+ QFutureSynchronizer<void> synchronizer;
+
+ QList<QFuture<void> > futures;
+ for (int i=0; i<100; i++) {
+ QFuture<void> future;
+ futures.append(future);
+ synchronizer.addFuture(future);
+ }
+
+ QCOMPARE(futures, synchronizer.futures());
+}
+
+void tst_QFutureSynchronizer::setFuture()
+{
+ QFutureSynchronizer<void> synchronizer;
+
+ for (int i=0; i<100; i++) {
+ synchronizer.addFuture(QFuture<void>());
+ }
+ QCOMPARE(synchronizer.futures().size(), 100);
+
+ QFuture<void> future;
+ synchronizer.setFuture(future);
+ QCOMPARE(synchronizer.futures().size(), 1);
+ QCOMPARE(synchronizer.futures().first(), future);
+}
+
+void tst_QFutureSynchronizer::waitForFinished()
+{
+ QFutureSynchronizer<void> synchronizer;
+
+ for (int i=0; i<100; i++) {
+ synchronizer.addFuture(QFuture<void>());
+ }
+ synchronizer.waitForFinished();
+ const QList<QFuture<void> > futures = synchronizer.futures();
+
+ for (int i=0; i<100; i++) {
+ QVERIFY(futures.at(i).isFinished());
+ }
+}
+
+QTEST_MAIN(tst_QFutureSynchronizer)
+
+#include "tst_qfuturesynchronizer.moc"
diff --git a/tests/auto/corelib/concurrent/qfuturewatcher/.gitignore b/tests/auto/corelib/concurrent/qfuturewatcher/.gitignore
new file mode 100644
index 0000000000..1d778431c5
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuturewatcher/.gitignore
@@ -0,0 +1 @@
+tst_qfuturewatcher
diff --git a/tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro b/tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro
new file mode 100644
index 0000000000..9de37d014f
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES += tst_qfuturewatcher.cpp
+QT = core core-private
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp
new file mode 100644
index 0000000000..d8fa2230f3
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp
@@ -0,0 +1,930 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QDebug>
+#include <QtTest/QtTest>
+
+#include <qfuture.h>
+#include "../qfuture/versioncheck.h"
+#include <qfuturewatcher.h>
+#include <qtconcurrentrun.h>
+#include <qtconcurrentmap.h>
+#include "../../../../shared/util.h"
+
+#ifndef QT_NO_CONCURRENT_TEST
+#include <private/qfutureinterface_p.h>
+
+using namespace QtConcurrent;
+
+#include <QtTest/QtTest>
+
+//#define PRINT
+
+class tst_QFutureWatcher: public QObject
+{
+ Q_OBJECT
+private slots:
+ void startFinish();
+ void progressValueChanged();
+ void canceled();
+ void resultAt();
+ void resultReadyAt();
+ void futureSignals();
+ void watchFinishedFuture();
+ void watchCanceledFuture();
+ void disconnectRunningFuture();
+ void toMuchProgress();
+ void progressText();
+ void sharedFutureInterface();
+ void changeFuture();
+ void cancelEvents();
+ void pauseEvents();
+ void finishedState();
+ void throttling();
+ void incrementalMapResults();
+ void incrementalFilterResults();
+ void qfutureSynchornizer();
+ void warnRace();
+};
+
+QTEST_MAIN(tst_QFutureWatcher)
+
+void sleeper()
+{
+ QTest::qSleep(100);
+}
+
+void tst_QFutureWatcher::startFinish()
+{
+ QFutureWatcher<void> futureWatcher;
+
+ QSignalSpy started(&futureWatcher, SIGNAL(started()));
+ QSignalSpy finished(&futureWatcher, SIGNAL(finished()));
+
+ futureWatcher.setFuture(QtConcurrent::run(sleeper));
+ QTest::qWait(10); // spin the event loop to deliver queued signals.
+ QCOMPARE(started.count(), 1);
+ QCOMPARE(finished.count(), 0);
+ futureWatcher.future().waitForFinished();
+ QTest::qWait(10);
+ QCOMPARE(started.count(), 1);
+ QCOMPARE(finished.count(), 1);
+}
+
+void mapSleeper(int &)
+{
+ QTest::qSleep(100);
+}
+
+QSet<int> progressValues;
+QSet<QString> progressTexts;
+QMutex mutex;
+class ProgressObject : public QObject
+{
+Q_OBJECT
+public slots:
+ void printProgress(int);
+ void printText(const QString &text);
+ void registerProgress(int);
+ void registerText(const QString &text);
+};
+
+void ProgressObject::printProgress(int progress)
+{
+ qDebug() << "thread" << QThread::currentThread() << "reports progress" << progress;
+}
+
+void ProgressObject::printText(const QString &text)
+{
+ qDebug() << "thread" << QThread::currentThread() << "reports progress text" << text;
+}
+
+void ProgressObject::registerProgress(int progress)
+{
+ QTest::qSleep(1);
+ progressValues.insert(progress);
+}
+
+void ProgressObject::registerText(const QString &text)
+{
+ QTest::qSleep(1);
+ progressTexts.insert(text);
+}
+
+
+QList<int> createList(int listSize)
+{
+ QList<int> list;
+ for (int i = 0; i < listSize; ++i) {
+ list.append(i);
+ }
+ return list;
+}
+
+void tst_QFutureWatcher::progressValueChanged()
+{
+#ifdef PRINT
+ qDebug() << "main thread" << QThread::currentThread();
+#endif
+
+ progressValues.clear();
+ const int listSize = 20;
+ QList<int> list = createList(listSize);
+
+ QFutureWatcher<void> futureWatcher;
+ ProgressObject progressObject;
+ QObject::connect(&futureWatcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+#ifdef PRINT
+ QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &progressObject, SLOT(printProgress(int)), Qt::DirectConnection );
+#endif
+ QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &progressObject, SLOT(registerProgress(int)));
+
+ futureWatcher.setFuture(QtConcurrent::map(list, mapSleeper));
+
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ futureWatcher.disconnect();
+ QVERIFY(progressValues.contains(0));
+ QVERIFY(progressValues.contains(listSize));
+}
+
+class CancelObject : public QObject
+{
+Q_OBJECT
+public:
+ bool wasCanceled;
+ CancelObject() : wasCanceled(false) {};
+public slots:
+ void cancel();
+};
+
+void CancelObject::cancel()
+{
+#ifdef PRINT
+ qDebug() << "thread" << QThread::currentThread() << "reports canceled";
+#endif
+ wasCanceled = true;
+}
+
+void tst_QFutureWatcher::canceled()
+{
+ const int listSize = 20;
+ QList<int> list = createList(listSize);
+
+ QFutureWatcher<void> futureWatcher;
+ QFuture<void> future;
+ CancelObject cancelObject;
+
+ QObject::connect(&futureWatcher, SIGNAL(canceled()), &cancelObject, SLOT(cancel()));
+ QObject::connect(&futureWatcher, SIGNAL(canceled()),
+ &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
+
+ future = QtConcurrent::map(list, mapSleeper);
+ futureWatcher.setFuture(future);
+ futureWatcher.cancel();
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QVERIFY(future.isCanceled());
+ QVERIFY(cancelObject.wasCanceled);
+ futureWatcher.disconnect();
+ future.waitForFinished();
+}
+
+class IntTask : public RunFunctionTask<int>
+{
+public:
+ void runFunctor()
+ {
+ result = 10;
+ }
+};
+
+void tst_QFutureWatcher::resultAt()
+{
+ QFutureWatcher<int> futureWatcher;
+ futureWatcher.setFuture((new IntTask())->start());
+ futureWatcher.waitForFinished();
+ QCOMPARE(futureWatcher.result(), 10);
+ QCOMPARE(futureWatcher.resultAt(0), 10);
+}
+
+void tst_QFutureWatcher::resultReadyAt()
+{
+ QFutureWatcher<int> futureWatcher;
+ QObject::connect(&futureWatcher, SIGNAL(resultReadyAt(int)), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
+
+ QFuture<int> future = (new IntTask())->start();
+ futureWatcher.setFuture(future);
+
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ // Setting the future again should give us another signal.
+ // (this is to prevent the race where the task associated
+ // with the future finishes before setFuture is called.)
+ futureWatcher.setFuture(QFuture<int>());
+ futureWatcher.setFuture(future);
+
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+}
+
+class SignalSlotObject : public QObject
+{
+Q_OBJECT
+
+signals:
+ void cancel();
+
+public slots:
+ void started()
+ {
+ qDebug() << "started called";
+ }
+
+ void finished()
+ {
+ qDebug() << "finished called";
+ }
+
+ void canceled()
+ {
+ qDebug() << "canceled called";
+ }
+
+#ifdef PRINT
+ void resultReadyAt(int index)
+ {
+ qDebug() << "result" << index << "ready";
+ }
+#else
+ void resultReadyAt(int) { }
+#endif
+ void progressValueChanged(int progress)
+ {
+ qDebug() << "progress" << progress;
+ }
+
+ void progressRangeChanged(int min, int max)
+ {
+ qDebug() << "progress range" << min << max;
+ }
+
+};
+
+void tst_QFutureWatcher::futureSignals()
+{
+ {
+ QFutureInterface<int> a;
+ QFutureWatcher<int> f;
+
+ SignalSlotObject object;
+#ifdef PRINT
+ connect(&f, SIGNAL(finished()), &object, SLOT(finished()));
+ connect(&f, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int)));
+#endif
+ // must connect to resultReadyAt so that the watcher can detect the connection
+ // (QSignalSpy does not trigger it.)
+ connect(&f, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+ a.reportStarted();
+ f.setFuture(a.future());
+
+ QSignalSpy progressSpy(&f, SIGNAL(progressValueChanged(int)));
+ const int progress = 1;
+ a.setProgressValue(progress);
+ QTest::qWait(10);
+ QCOMPARE(progressSpy.count(), 2);
+ QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 0);
+ QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 1);
+
+ QSignalSpy finishedSpy(&f, SIGNAL(finished()));
+ QSignalSpy resultReadySpy(&f, SIGNAL(resultReadyAt(int)));
+
+ const int result = 10;
+ a.reportResult(&result);
+ QTest::qWait(10);
+ QCOMPARE(resultReadySpy.count(), 1);
+ a.reportFinished(&result);
+ QTest::qWait(10);
+
+ QCOMPARE(resultReadySpy.count(), 2);
+ QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 0); // check the index
+ QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 1);
+
+ QCOMPARE(finishedSpy.count(), 1);
+ }
+}
+
+void tst_QFutureWatcher::watchFinishedFuture()
+{
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+
+ QFuture<int> f = iface.future();
+
+ int value = 100;
+ iface.reportFinished(&value);
+
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+#ifdef PRINT
+ connect(&watcher, SIGNAL(started()), &object, SLOT(started()));
+ connect(&watcher, SIGNAL(canceled()), &object, SLOT(canceled()));
+ connect(&watcher, SIGNAL(finished()), &object, SLOT(finished()));
+ connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int)));
+ connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &object, SLOT(progressRangeChanged(int, int)));
+#endif
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+
+ QSignalSpy startedSpy(&watcher, SIGNAL(started()));
+ QSignalSpy finishedSpy(&watcher, SIGNAL(finished()));
+ QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int)));
+ QSignalSpy canceledSpy(&watcher, SIGNAL(canceled()));
+
+ watcher.setFuture(f);
+ QTest::qWait(10);
+
+ QCOMPARE(startedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(resultReadySpy.count(), 1);
+ QCOMPARE(canceledSpy.count(), 0);
+}
+
+void tst_QFutureWatcher::watchCanceledFuture()
+{
+ QFuture<int> f;
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+#ifdef PRINT
+ connect(&watcher, SIGNAL(started()), &object, SLOT(started()));
+ connect(&watcher, SIGNAL(canceled()), &object, SLOT(canceled()));
+ connect(&watcher, SIGNAL(finished()), &object, SLOT(finished()));
+ connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int)));
+ connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &object, SLOT(progressRangeChanged(int, int)));
+#endif
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+
+ QSignalSpy startedSpy(&watcher, SIGNAL(started()));
+ QSignalSpy finishedSpy(&watcher, SIGNAL(finished()));
+ QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int)));
+ QSignalSpy canceledSpy(&watcher, SIGNAL(canceled()));
+
+ watcher.setFuture(f);
+ QTest::qWait(10);
+
+ QCOMPARE(startedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(resultReadySpy.count(), 0);
+ QCOMPARE(canceledSpy.count(), 1);
+}
+
+void tst_QFutureWatcher::disconnectRunningFuture()
+{
+ QFutureInterface<int> a;
+ a.reportStarted();
+
+ QFuture<int> f = a.future();
+ QFutureWatcher<int> *watcher = new QFutureWatcher<int>();
+ watcher->setFuture(f);
+
+ SignalSlotObject object;
+ connect(watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+
+ QSignalSpy finishedSpy(watcher, SIGNAL(finished()));
+ QSignalSpy resultReadySpy(watcher, SIGNAL(resultReadyAt(int)));
+
+ const int result = 10;
+ a.reportResult(&result);
+ QTest::qWait(10);
+ QCOMPARE(resultReadySpy.count(), 1);
+
+ delete watcher;
+
+ a.reportResult(&result);
+ QTest::qWait(10);
+ QCOMPARE(resultReadySpy.count(), 1);
+
+ a.reportFinished(&result);
+ QTest::qWait(10);
+ QCOMPARE(finishedSpy.count(), 0);
+}
+
+const int maxProgress = 100000;
+class ProgressEmitterTask : public RunFunctionTask<void>
+{
+public:
+ void runFunctor()
+ {
+ setProgressRange(0, maxProgress);
+ for (int p = 0; p <= maxProgress; ++p)
+ setProgressValue(p);
+ }
+};
+
+void tst_QFutureWatcher::toMuchProgress()
+{
+ progressValues.clear();
+ ProgressObject o;
+
+ QFutureWatcher<void> f;
+ QObject::connect(&f, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+#ifdef PRINT
+ QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int)));
+#endif
+ QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int)));
+ f.setFuture((new ProgressEmitterTask())->start());
+
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(progressValues.contains(maxProgress));
+}
+
+template <typename T>
+class ProgressTextTask : public RunFunctionTask<T>
+{
+public:
+ void runFunctor()
+ {
+ this->setProgressValueAndText(1, QLatin1String("Foo 1"));
+
+ while (this->isProgressUpdateNeeded() == false)
+ QTest::qSleep(1);
+ this->setProgressValueAndText(2, QLatin1String("Foo 2"));
+
+ while (this->isProgressUpdateNeeded() == false)
+ QTest::qSleep(1);
+ this->setProgressValueAndText(3, QLatin1String("Foo 3"));
+
+ while (this->isProgressUpdateNeeded() == false)
+ QTest::qSleep(1);
+ this->setProgressValueAndText(4, QLatin1String("Foo 4"));
+ }
+};
+
+void tst_QFutureWatcher::progressText()
+{
+ { // instantiate API for T=int and T=void.
+ ProgressTextTask<int> a;
+ ProgressTextTask<void> b;
+ }
+ {
+ progressValues.clear();
+ progressTexts.clear();
+ QFuture<int> f = ((new ProgressTextTask<int>())->start());
+ QFutureWatcher<int> watcher;
+ ProgressObject o;
+ QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+#ifdef PRINT
+ QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int)));
+ QObject::connect(&watcher, SIGNAL(progressTextChanged(const QString &)), &o, SLOT(printText(const QString &)));
+#endif
+ QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int)));
+ QObject::connect(&watcher, SIGNAL(progressTextChanged(const QString &)), &o, SLOT(registerText(const QString &)));
+
+ watcher.setFuture(f);
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QCOMPARE(f.progressText(), QLatin1String("Foo 4"));
+ QCOMPARE(f.progressValue(), 4);
+ QVERIFY(progressValues.contains(1));
+ QVERIFY(progressValues.contains(2));
+ QVERIFY(progressValues.contains(3));
+ QVERIFY(progressValues.contains(4));
+ QVERIFY(progressTexts.contains(QLatin1String("Foo 1")));
+ QVERIFY(progressTexts.contains(QLatin1String("Foo 2")));
+ QVERIFY(progressTexts.contains(QLatin1String("Foo 3")));
+ QVERIFY(progressTexts.contains(QLatin1String("Foo 4")));
+ }
+}
+
+template <typename T>
+void callInterface(T &obj)
+{
+ obj.progressValue();
+ obj.progressMinimum();
+ obj.progressMaximum();
+ obj.progressText();
+
+ obj.isStarted();
+ obj.isFinished();
+ obj.isRunning();
+ obj.isCanceled();
+ obj.isPaused();
+
+ obj.cancel();
+ obj.pause();
+ obj.resume();
+ obj.togglePaused();
+ obj.waitForFinished();
+
+ const T& objConst = obj;
+ objConst.progressValue();
+ objConst.progressMinimum();
+ objConst.progressMaximum();
+ objConst.progressText();
+
+ objConst.isStarted();
+ objConst.isFinished();
+ objConst.isRunning();
+ objConst.isCanceled();
+ objConst.isPaused();
+}
+
+template <typename T>
+void callInterface(const T &obj)
+{
+ obj.result();
+ obj.resultAt(0);
+}
+
+
+// QFutureWatcher and QFuture has a similar interface. Test
+// that the functions we want ot have in both are actually
+// there.
+void tst_QFutureWatcher::sharedFutureInterface()
+{
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+
+ QFuture<int> intFuture = iface.future();
+
+ int value = 0;
+ iface.reportFinished(&value);
+
+ QFuture<void> voidFuture;
+ QFutureWatcher<int> intWatcher;
+ intWatcher.setFuture(intFuture);
+ QFutureWatcher<void> voidWatcher;
+
+ callInterface(intFuture);
+ callInterface(voidFuture);
+ callInterface(intWatcher);
+ callInterface(voidWatcher);
+
+ callInterface(intFuture);
+ callInterface(intWatcher);
+}
+
+void tst_QFutureWatcher::changeFuture()
+{
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+
+ QFuture<int> a = iface.future();
+
+ int value = 0;
+ iface.reportFinished(&value);
+
+ QFuture<int> b;
+
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+ QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int)));
+
+ watcher.setFuture(a); // Watch 'a' which will genere a resultReady event.
+ watcher.setFuture(b); // But oh no! we're switching to another future
+ QTest::qWait(10); // before the event gets delivered.
+
+ QCOMPARE(resultReadySpy.count(), 0);
+
+ watcher.setFuture(a);
+ watcher.setFuture(b);
+ watcher.setFuture(a); // setting it back gets us one event, not two.
+ QTest::qWait(10);
+
+ QCOMPARE(resultReadySpy.count(), 1);
+}
+
+// Test that events aren't delivered from canceled futures
+void tst_QFutureWatcher::cancelEvents()
+{
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+
+ QFuture<int> a = iface.future();
+
+ int value = 0;
+ iface.reportFinished(&value);
+
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+ QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int)));
+
+ watcher.setFuture(a);
+ watcher.cancel();
+
+ QTest::qWait(10);
+
+ QCOMPARE(resultReadySpy.count(), 0);
+}
+
+// Tests that events from paused futures are saved and
+// delivered on resume.
+void tst_QFutureWatcher::pauseEvents()
+{
+ {
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+
+ QFuture<int> a = iface.future();
+
+ int value = 0;
+ iface.reportFinished(&value);
+
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+ QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int)));
+
+ watcher.setFuture(a);
+ watcher.pause();
+
+ QTest::qWait(10);
+ QCOMPARE(resultReadySpy.count(), 0);
+
+ watcher.resume();
+ QTest::qWait(10);
+ QCOMPARE(resultReadySpy.count(), 1);
+ }
+ {
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+
+ QFuture<int> a = iface.future();
+
+ int value = 0;
+ iface.reportFinished(&value);
+
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+ QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int)));
+
+ watcher.setFuture(a);
+ a.pause();
+
+ QFuture<int> b;
+ watcher.setFuture(b); // If we watch b instead, resuming a
+ a.resume(); // should give us no results.
+
+ QTest::qWait(10);
+ QCOMPARE(resultReadySpy.count(), 0);
+ }
+}
+
+// Test that the finished state for the watcher gets
+// set when the finished event is delivered.
+// This means it will lag the finished state for the future,
+// but makes it more useful.
+void tst_QFutureWatcher::finishedState()
+{
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+ QFuture<int> future = iface.future();
+ QFutureWatcher<int> watcher;
+
+ watcher.setFuture(future);
+ QTest::qWait(10);
+
+ iface.reportFinished();
+ QVERIFY(future.isFinished());
+ QVERIFY(watcher.isFinished() == false);
+
+ QTest::qWait(10);
+ QVERIFY(watcher.isFinished());
+}
+
+/*
+ Verify that throttling kicks in if you report a lot of results,
+ and that it clears when the result events are processed.
+*/
+void tst_QFutureWatcher::throttling()
+{
+ QFutureInterface<int> iface;
+ iface.reportStarted();
+ QFuture<int> future = iface.future();
+ QFutureWatcher<int> watcher;
+ watcher.setFuture(future);
+
+ QVERIFY(iface.isThrottled() == false);
+
+ for (int i = 0; i < 1000; ++i) {
+ int result = 0;
+ iface.reportResult(result);
+ }
+
+ QVERIFY(iface.isThrottled() == true);
+
+ QTest::qWait(100); // process events.
+
+ QVERIFY(iface.isThrottled() == false);
+
+ iface.reportFinished();
+}
+
+int mapper(const int &i)
+{
+ return i;
+}
+
+class ResultReadyTester : public QObject
+{
+Q_OBJECT
+public:
+ ResultReadyTester(QFutureWatcher<int> *watcher)
+ :m_watcher(watcher), filter(false), ok(true), count(0)
+ {
+
+ }
+public slots:
+ void resultReadyAt(int index)
+ {
+ ++count;
+ if (m_watcher->future().isResultReadyAt(index) == false)
+ ok = false;
+ if (!filter && m_watcher->future().resultAt(index) != index)
+ ok = false;
+ if (filter && m_watcher->future().resultAt(index) != index * 2 + 1)
+ ok = false;
+ }
+public:
+ QFutureWatcher<int> *m_watcher;
+ bool filter;
+ bool ok;
+ int count;
+};
+
+void tst_QFutureWatcher::incrementalMapResults()
+{
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+#ifdef PRINT
+ connect(&watcher, SIGNAL(finished()), &object, SLOT(finished()));
+ connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int)));
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+#endif
+
+ QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ ResultReadyTester resultReadyTester(&watcher);
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &resultReadyTester, SLOT(resultReadyAt(int)));
+
+ const int count = 10000;
+ QList<int> ints;
+ for (int i = 0; i < count; ++i)
+ ints << i;
+
+ QFuture<int> future = QtConcurrent::mapped(ints, mapper);
+ watcher.setFuture(future);
+
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QCOMPARE(resultReadyTester.count, count);
+ QVERIFY(resultReadyTester.ok);
+ QVERIFY(watcher.isFinished());
+ future.waitForFinished();
+}
+
+bool filterer(int i)
+{
+ return (i % 2);
+}
+
+void tst_QFutureWatcher::incrementalFilterResults()
+{
+ QFutureWatcher<int> watcher;
+
+ SignalSlotObject object;
+#ifdef PRINT
+ connect(&watcher, SIGNAL(finished()), &object, SLOT(finished()));
+ connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int)));
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+#endif
+
+ QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+
+ ResultReadyTester resultReadyTester(&watcher);
+ resultReadyTester.filter = true;
+ connect(&watcher, SIGNAL(resultReadyAt(int)), &resultReadyTester, SLOT(resultReadyAt(int)));
+
+ const int count = 10000;
+ QList<int> ints;
+ for (int i = 0; i < count; ++i)
+ ints << i;
+
+ QFuture<int> future = QtConcurrent::filtered(ints, filterer);
+ watcher.setFuture(future);
+
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QCOMPARE(resultReadyTester.count, count / 2);
+ QVERIFY(resultReadyTester.ok);
+ QVERIFY(watcher.isFinished());
+ future.waitForFinished();
+}
+
+void tst_QFutureWatcher::qfutureSynchornizer()
+{
+ int taskCount = 1000;
+ QTime t;
+ t.start();
+
+ {
+ QFutureSynchronizer<void> sync;
+
+ sync.setCancelOnWait(true);
+ for (int i = 0; i < taskCount; ++i) {
+ sync.addFuture(run(sleeper));
+ }
+ }
+
+ // Test that we're not running each task.
+ QVERIFY(t.elapsed() < taskCount * 10);
+}
+
+class DummyObject : public QObject {
+ Q_OBJECT
+public slots:
+ void dummySlot() {}
+public:
+ static void function(QMutex *m)
+ {
+ QMutexLocker lock(m);
+ }
+};
+
+void tst_QFutureWatcher::warnRace()
+{
+#ifndef Q_OS_MAC //I don't know why it is not working on mac
+#ifndef QT_NO_DEBUG
+ QTest::ignoreMessage(QtWarningMsg, "QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race");
+#endif
+#endif
+ QFutureWatcher<void> watcher;
+ DummyObject object;
+ QMutex mutex;
+ mutex.lock();
+
+ QFuture<void> future = QtConcurrent::run(DummyObject::function, &mutex);
+ watcher.setFuture(future);
+ QTRY_VERIFY(future.isStarted());
+ connect(&watcher, SIGNAL(finished()), &object, SLOT(dummySlot()));
+ mutex.unlock();
+ future.waitForFinished();
+}
+
+#include "tst_qfuturewatcher.moc"
+
+#else
+QTEST_NOOP_MAIN
+#endif
diff --git a/tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore
new file mode 100644
index 0000000000..f93d27e009
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore
@@ -0,0 +1 @@
+tst_qtconcurrentfilter
diff --git a/tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro b/tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro
new file mode 100644
index 0000000000..62d4908e69
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+DEFINES += QT_STRICT_ITERATORS
+SOURCES += tst_qtconcurrentfilter.cpp
+QT = core
+CONFIG += parallel_test
+linux*:CONFIG += insignificant_test
diff --git a/tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp b/tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp
new file mode 100644
index 0000000000..33611d7331
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp
@@ -0,0 +1,1546 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtconcurrentfilter.h>
+#include <QCoreApplication>
+#include <QList>
+#include <QLinkedList>
+#include <QtTest/QtTest>
+
+#include "../qtconcurrentmap/functions.h"
+#include "../qfuture/versioncheck.h"
+
+class tst_QtConcurrentFilter : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void filter();
+ void filtered();
+ void filteredReduced();
+ void resultAt();
+ void incrementalResults();
+ void noDetatch();
+ void stlContainers();
+};
+
+#if !defined (QT_NO_CONCURRENT_TEST) && !defined(QT_NO_CONCURRENT_FILTER)
+
+void tst_QtConcurrentFilter::filter()
+{
+ // functor
+ {
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(list, KeepEvenIntegers()).waitForFinished();
+ QCOMPARE(list, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(list, KeepEvenIntegers());
+ QCOMPARE(list, QList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(linkedList, KeepEvenIntegers()).waitForFinished();
+ QCOMPARE(linkedList, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(linkedList, KeepEvenIntegers());
+ QCOMPARE(linkedList, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QVector<int> vector;
+ vector << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(vector, KeepEvenIntegers()).waitForFinished();
+ QCOMPARE(vector, QVector<int>() << 2 << 4);
+ }
+ {
+ QVector<int> vector;
+ vector << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(vector, KeepEvenIntegers());
+ QCOMPARE(vector, QVector<int>() << 2 << 4);
+ }
+
+
+ // function
+ {
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(list, keepEvenIntegers).waitForFinished();
+ QCOMPARE(list, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(list, keepEvenIntegers);
+ QCOMPARE(list, QList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(linkedList, keepEvenIntegers).waitForFinished();
+ QCOMPARE(linkedList, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(linkedList, keepEvenIntegers);
+ QCOMPARE(linkedList, QLinkedList<int>() << 2 << 4);
+ }
+
+ // bound function
+ {
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(list, keepEvenIntegers).waitForFinished();
+ QCOMPARE(list, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(list, keepEvenIntegers);
+ QCOMPARE(list, QList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(linkedList, keepEvenIntegers).waitForFinished();
+ QCOMPARE(linkedList, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(linkedList, keepEvenIntegers);
+ QCOMPARE(linkedList, QLinkedList<int>() << 2 << 4);
+ }
+
+ // member
+ {
+ QList<Number> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(list, &Number::isEven).waitForFinished();
+ QCOMPARE(list, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> list;
+ list << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(list, &Number::isEven);
+ QCOMPARE(list, QList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::filter(linkedList, &Number::isEven).waitForFinished();
+ QCOMPARE(linkedList, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QtConcurrent::blockingFilter(linkedList, &Number::isEven);
+ QCOMPARE(linkedList, QLinkedList<Number>() << 2 << 4);
+ }
+}
+
+void tst_QtConcurrentFilter::filtered()
+{
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+
+ // functor
+ {
+ QFuture<int> f = QtConcurrent::filtered(list, KeepEvenIntegers());
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(list.begin(), list.end(), KeepEvenIntegers());
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers());
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered(list, KeepEvenIntegers());
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.begin(),
+ list.end(),
+ KeepEvenIntegers());
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers());
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+
+ {
+ QVector<int> vector;
+ vector << 1 << 2 << 3 << 4;
+ QVector<int> vector2 = QtConcurrent::blockingFiltered(vector, KeepEvenIntegers());
+ QCOMPARE(vector2, QVector<int>() << 2 << 4);
+ }
+ {
+ QVector<int> vector;
+ vector << 1 << 2 << 3 << 4;
+ QFuture<int> f = QtConcurrent::filtered(vector, KeepEvenIntegers());
+ QCOMPARE(f.results(), QList<int>() << 2 << 4);
+ }
+
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered(linkedList, KeepEvenIntegers());
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QFuture<int> f = QtConcurrent::filtered(linkedList, KeepEvenIntegers());
+ QCOMPARE(f.results(), QList<int>() << 2 << 4);
+ }
+
+ // function
+ {
+ QFuture<int> f = QtConcurrent::filtered(list, keepEvenIntegers);
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(list.begin(), list.end(), keepEvenIntegers);
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers);
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered(list, keepEvenIntegers);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.begin(),
+ list.end(),
+ keepEvenIntegers);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+
+ // bound function
+ {
+ QFuture<int> f = QtConcurrent::filtered(list, keepEvenIntegers);
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(list.begin(), list.end(), keepEvenIntegers);
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers);
+ QList<int> list2 = f.results();
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered(list, keepEvenIntegers);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.begin(),
+ list.end(),
+ keepEvenIntegers);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+
+ // const member function
+ {
+ QList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QFuture<Number> f = QtConcurrent::filtered(integers, &Number::isEven);
+ QList<Number> list2 = f.results();
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QFuture<Number> f = QtConcurrent::filtered(integers.begin(),
+ integers.end(),
+ &Number::isEven);
+ QList<Number> list2 = f.results();
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QFuture<Number> f = QtConcurrent::filtered(integers.constBegin(),
+ integers.constEnd(),
+ &Number::isEven);
+ QList<Number> list2 = f.results();
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::blockingFiltered(integers, &Number::isEven);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::blockingFiltered<QList<Number> >(integers.begin(),
+ integers.end(),
+ &Number::isEven);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QList<Number> list2 =
+ QtConcurrent::blockingFiltered<QList<Number> >(integers.constBegin(),
+ integers.constEnd(),
+ &Number::isEven);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+
+ // same thing on linked lists
+
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+
+ // functor
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList, KeepEvenIntegers());
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers());
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers());
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered(linkedList, KeepEvenIntegers());
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered<QLinkedList<int> >(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers());
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered<QLinkedList<int> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers());
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+
+ // function
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList, keepEvenIntegers);
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers);
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers);
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered(linkedList, keepEvenIntegers);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered<QLinkedList<int> >(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered<QLinkedList<int> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+
+ // bound function
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList, keepEvenIntegers);
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers);
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QFuture<int> f = QtConcurrent::filtered(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers);
+ QList<int> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered(linkedList, keepEvenIntegers);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered<QLinkedList<int> >(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFiltered<QLinkedList<int> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+
+ // const member function
+ {
+ QLinkedList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QFuture<Number> f = QtConcurrent::filtered(integers, &Number::isEven);
+ QList<Number> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QFuture<Number> f = QtConcurrent::filtered(integers.begin(),
+ integers.end(),
+ &Number::isEven);
+ QList<Number> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QFuture<Number> f = QtConcurrent::filtered(integers.constBegin(),
+ integers.constEnd(),
+ &Number::isEven);
+ QList<Number> linkedList2 = f.results();
+ QCOMPARE(linkedList2, QList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::blockingFiltered(integers, &Number::isEven);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::blockingFiltered<QLinkedList<Number> >(integers.begin(),
+ integers.end(),
+ &Number::isEven);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> integers;
+ integers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 =
+ QtConcurrent::blockingFiltered<QLinkedList<Number> >(integers.constBegin(),
+ integers.constEnd(),
+ &Number::isEven);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+}
+
+void tst_QtConcurrentFilter::filteredReduced()
+{
+ QList<int> list;
+ list << 1 << 2 << 3 << 4;
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3 << 4;
+
+ // functor-functor
+ {
+ int sum = QtConcurrent::filteredReduced<int>(list, KeepEvenIntegers(), IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(list, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ QVector<int> vector;
+ vector << 1 << 2 << 3 << 4;
+ int sum = QtConcurrent::filteredReduced<int>(vector, KeepEvenIntegers(), IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+
+ {
+ int sum = QtConcurrent::filteredReduced<int>(list.begin(),
+ list.end(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(list, KeepEvenIntegers(), IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(list, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(list.begin(),
+ list.end(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+
+ // function-functor
+ {
+ int sum = QtConcurrent::filteredReduced<int>(list, keepEvenIntegers, IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(list, keepEvenIntegers, IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+
+ // functor-function
+ {
+ int sum = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(list.begin(),
+ list.end(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(list.begin(),
+ list.end(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+
+ // function-function
+ {
+ int sum = QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+
+ // functor-member
+ {
+ QList<int> list2 = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), &QList<int>::push_back, QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::filteredReduced(list.begin(),
+ list.end(),
+ KeepEvenIntegers(),
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::filteredReduced(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers(),
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), &QList<int>::push_back, QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.begin(),
+ list.end(),
+ KeepEvenIntegers(),
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(),
+ list.constEnd(),
+ KeepEvenIntegers(),
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+
+ // member-functor
+ {
+ int sum = QtConcurrent::filteredReduced<int>(numberList, &Number::isEven, NumberSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(QList<Number>(numberList),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(numberList.begin(),
+ numberList.end(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(numberList, &Number::isEven, NumberSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(QList<Number>(numberList),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(numberList.begin(),
+ numberList.end(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+
+ // member-member
+ {
+ QList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::filteredReduced(numbers,
+ &Number::isEven,
+ &QList<Number>::push_back, QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::filteredReduced(numbers.begin(),
+ numbers.end(),
+ &Number::isEven,
+ &QList<Number>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::filteredReduced(numbers.constBegin(),
+ numbers.constEnd(),
+ &Number::isEven,
+ &QList<Number>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::blockingFilteredReduced(numbers,
+ &Number::isEven,
+ &QList<Number>::push_back, QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::blockingFilteredReduced(numbers.begin(),
+ numbers.end(),
+ &Number::isEven,
+ &QList<Number>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+ {
+ QList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QList<Number> list2 = QtConcurrent::blockingFilteredReduced(numbers.constBegin(),
+ numbers.constEnd(),
+ &Number::isEven,
+ &QList<Number>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<Number>() << 2 << 4);
+ }
+
+ // function-member
+ {
+ QList<int> list2 = QtConcurrent::filteredReduced(list, keepEvenIntegers, &QList<int>::push_back, QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::filteredReduced(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::filteredReduced(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, &QList<int>::push_back, QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.begin(),
+ list.end(),
+ keepEvenIntegers,
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+ {
+ QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(),
+ list.constEnd(),
+ keepEvenIntegers,
+ &QList<int>::push_back,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 2 << 4);
+ }
+
+ // member-function
+ {
+ int sum = QtConcurrent::filteredReduced(numberList, &Number::isEven, numberSumReduce);
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced(QList<Number>(numberList),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(numberList.begin(),
+ numberList.end(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(numberList, &Number::isEven, numberSumReduce);
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced(QList<Number>(numberList),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(numberList.begin(),
+ numberList.end(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+
+ // same as above on linked lists
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3 << 4;
+ QLinkedList<Number> numberLinkedList;
+ numberLinkedList << 1 << 2 << 3 << 4;
+
+ // functor-functor
+ {
+ int sum = QtConcurrent::filteredReduced<int>(linkedList, KeepEvenIntegers(), IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(linkedList, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(linkedList, KeepEvenIntegers(), IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(linkedList, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers(),
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+
+ // function-functor
+ {
+ int sum = QtConcurrent::filteredReduced<int>(linkedList, keepEvenIntegers, IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(linkedList, keepEvenIntegers, IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ }
+
+ // functor-function
+ {
+ int sum = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers(),
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+
+ // function-function
+ {
+ int sum = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ }
+
+ // functor-member
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), &QLinkedList<int>::append, QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::filteredReduced(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers(),
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::filteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers(),
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), &QLinkedList<int>::append, QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(),
+ linkedList.end(),
+ KeepEvenIntegers(),
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ KeepEvenIntegers(),
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+
+ // member-functor
+ {
+ int sum = QtConcurrent::filteredReduced<int>(numberLinkedList, &Number::isEven, NumberSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced<int>(QLinkedList<Number>(numberLinkedList),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(numberLinkedList.begin(),
+ numberLinkedList.end(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced<int>(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(numberLinkedList, &Number::isEven, NumberSumReduce());
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced<int>(QLinkedList<Number>(numberLinkedList),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(numberLinkedList.begin(),
+ numberLinkedList.end(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced<int>(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::isEven,
+ NumberSumReduce());
+ QCOMPARE(sum, 6);
+ }
+
+ // member-member
+ {
+ QLinkedList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::filteredReduced(numbers,
+ &Number::isEven,
+ &QLinkedList<Number>::append, QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::filteredReduced(numbers.begin(),
+ numbers.end(),
+ &Number::isEven,
+ &QLinkedList<Number>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::filteredReduced(numbers.constBegin(),
+ numbers.constEnd(),
+ &Number::isEven,
+ &QLinkedList<Number>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::blockingFilteredReduced(numbers,
+ &Number::isEven,
+ &QLinkedList<Number>::append, QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::blockingFilteredReduced(numbers.begin(),
+ numbers.end(),
+ &Number::isEven,
+ &QLinkedList<Number>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+ {
+ QLinkedList<Number> numbers;
+ numbers << 1 << 2 << 3 << 4;
+ QLinkedList<Number> linkedList2 = QtConcurrent::blockingFilteredReduced(numbers.constBegin(),
+ numbers.constEnd(),
+ &Number::isEven,
+ &QLinkedList<Number>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<Number>() << 2 << 4);
+ }
+
+ // function-member
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, &QLinkedList<int>::append, QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::filteredReduced(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::filteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, &QLinkedList<int>::append, QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(),
+ linkedList.end(),
+ keepEvenIntegers,
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ keepEvenIntegers,
+ &QLinkedList<int>::append,
+ QtConcurrent::OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4);
+ }
+
+ // member-function
+ {
+ int sum = QtConcurrent::filteredReduced(numberLinkedList, &Number::isEven, numberSumReduce);
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::filteredReduced(QLinkedList<Number>(numberLinkedList),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(numberLinkedList.begin(),
+ numberLinkedList.end(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::filteredReduced(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList, &Number::isEven, numberSumReduce);
+ QCOMPARE(sum, 6);
+
+ int sum2 = QtConcurrent::blockingFilteredReduced(QLinkedList<Number>(numberLinkedList),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum2, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.begin(),
+ numberLinkedList.end(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::isEven,
+ numberSumReduce);
+ QCOMPARE(sum, 6);
+ }
+
+ // ### the same as above, with an initial result value
+}
+
+bool filterfn(int i)
+{
+ return (i % 2);
+}
+
+void tst_QtConcurrentFilter::resultAt()
+{
+
+ QList<int> ints;
+ for (int i=0; i < 1000; ++i)
+ ints << i;
+
+ QFuture<int> future = QtConcurrent::filtered(ints, filterfn);
+ future.waitForFinished();
+
+
+ for (int i = 0; i < future.resultCount(); ++i) {
+ QCOMPARE(future.resultAt(i), ints.at(i * 2 + 1));
+ }
+
+}
+
+bool waitFilterfn(const int &i)
+{
+ QTest::qWait(1);
+ return (i % 2);
+}
+
+void tst_QtConcurrentFilter::incrementalResults()
+{
+ const int count = 200;
+ QList<int> ints;
+ for (int i=0; i < count; ++i)
+ ints << i;
+
+ QFuture<int> future = QtConcurrent::filtered(ints, waitFilterfn);
+
+ QList<int> results;
+
+ while (future.isFinished() == false) {
+ for (int i = 0; i < future.resultCount(); ++i) {
+ results += future.resultAt(i);
+ }
+ QTest::qWait(1);
+ }
+
+ QCOMPARE(future.isFinished(), true);
+ QCOMPARE(future.resultCount(), count / 2);
+ QCOMPARE(future.results().count(), count / 2);
+}
+
+void tst_QtConcurrentFilter::noDetatch()
+{
+ {
+ QList<int> l = QList<int>() << 1;
+ QVERIFY(l.isDetached());
+
+ QList<int> ll = l;
+ QVERIFY(l.isDetached() == false);
+
+ QtConcurrent::filtered(l, waitFilterfn).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+
+ QtConcurrent::blockingFiltered(l, waitFilterfn);
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+
+ QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+
+ QtConcurrent::filter(l, waitFilterfn).waitForFinished();
+ QVERIFY(l.isDetached() == true);
+ QVERIFY(ll.isDetached() == true);
+ }
+ {
+ const QList<int> l = QList<int>() << 1;
+ QVERIFY(l.isDetached());
+
+ const QList<int> ll = l;
+ QVERIFY(l.isDetached() == false);
+
+ QtConcurrent::filtered(l, waitFilterfn).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+
+ QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+ }
+}
+
+void tst_QtConcurrentFilter::stlContainers()
+{
+#ifdef QT_NO_STL
+ QSKIP("Qt compiled without STL support", SkipAll);
+#else
+ std::vector<int> vector;
+ vector.push_back(1);
+ vector.push_back(2);
+
+ std::vector<int> vector2 = QtConcurrent::blockingFiltered(vector, waitFilterfn);
+ QCOMPARE(vector2.size(), (std::vector<int>::size_type)(1));
+ QCOMPARE(vector2[0], 1);
+
+ std::list<int> list;
+ list.push_back(1);
+ list.push_back(2);
+
+ std::list<int> list2 = QtConcurrent::blockingFiltered(list, waitFilterfn);
+ QCOMPARE(list2.size(), (std::list<int>::size_type)(1));
+ QCOMPARE(*list2.begin(), 1);
+
+ QtConcurrent::filtered(list, waitFilterfn).waitForFinished();
+ QtConcurrent::filtered(vector, waitFilterfn).waitForFinished();
+ QtConcurrent::filtered(vector.begin(), vector.end(), waitFilterfn).waitForFinished();
+
+ QtConcurrent::blockingFilter(list, waitFilterfn);
+ QCOMPARE(list2.size(), (std::list<int>::size_type)(1));
+ QCOMPARE(*list2.begin(), 1);
+#endif
+}
+
+QTEST_MAIN(tst_QtConcurrentFilter)
+
+#else
+
+void tst_QtConcurrentFilter::filter() {}
+void tst_QtConcurrentFilter::filtered() {}
+void tst_QtConcurrentFilter::filteredReduced() {}
+void tst_QtConcurrentFilter::resultAt() {}
+void tst_QtConcurrentFilter::incrementalResults() {}
+void tst_QtConcurrentFilter::stlContainers() {}
+void tst_QtConcurrentFilter::noDetatch() {}
+
+QTEST_NOOP_MAIN
+#endif
+
+#include "tst_qtconcurrentfilter.moc"
diff --git a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore
new file mode 100644
index 0000000000..ac5dec4db6
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore
@@ -0,0 +1 @@
+tst_qtconcurrentiteratekernel
diff --git a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro
new file mode 100644
index 0000000000..a61d275241
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qtconcurrentiteratekernel.cpp
+QT = core
+CONFIG += parallel_test
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
new file mode 100644
index 0000000000..521c517d90
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QThread>
+#include "../qfuture/versioncheck.h"
+
+struct TestIterator
+{
+ TestIterator(int i)
+ :i(i) { }
+
+ int operator-(const TestIterator &other)
+ {
+ return i - other.i;
+ }
+
+ TestIterator& operator++()
+ {
+ ++i;
+ return *this;
+ }
+
+ bool operator!=(const TestIterator &other) const
+ {
+ return i != other.i;
+ }
+
+ int i;
+};
+
+#include <qiterator.h>
+#ifndef QT_NO_STL
+namespace std {
+template <>
+struct iterator_traits<TestIterator>
+{
+ typedef random_access_iterator_tag iterator_category;
+};
+
+int distance(TestIterator &a, TestIterator &b)
+{
+ return b - a;
+}
+
+}
+#endif
+
+
+#include <qtconcurrentiteratekernel.h>
+#include <QtTest/QtTest>
+
+#ifndef QT_NO_CONCURRENT_TEST
+
+using namespace QtConcurrent;
+
+class tst_QtConcurrentIterateKernel: public QObject
+{
+ Q_OBJECT
+private slots:
+ // "for" iteration tests:
+ void instantiate();
+ void cancel();
+ void stresstest();
+ void noIterations();
+ void throttling();
+ void blockSize();
+ void multipleResults();
+#if 0
+ //"while" iterations tests:
+ void instantiateWhile();
+ void stresstestWhile();
+#endif
+};
+
+QAtomicInt iterations;
+class PrintFor : public IterateKernel<TestIterator, void>
+{
+public:
+ PrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) {iterations = 0; }
+ bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
+ {
+ iterations.fetchAndAddRelaxed(end - begin);
+#ifdef PRINT
+ qDebug() << QThread::currentThread() << "iteration" << begin << "to" << end << "(exclusive)";
+#endif
+ return false;
+ }
+ bool runIteration(TestIterator it, int index , void *result)
+ {
+ return runIterations(it, index, index + 1, result);
+ }
+
+};
+
+class SleepPrintFor : public IterateKernel<TestIterator, void>
+{
+public:
+ SleepPrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) {iterations = 0; }
+ inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
+ {
+ QTest::qSleep(200);
+ iterations.fetchAndAddRelaxed(end - begin);
+#ifdef PRINT
+ qDebug() << QThread::currentThread() << "iteration" << begin << "to" << end << "(exclusive)";
+#endif
+ return false;
+ }
+ bool runIteration(TestIterator it, int index , void *result)
+ {
+ return runIterations(it, index, index + 1, result);
+ }
+};
+
+
+void tst_QtConcurrentIterateKernel::instantiate()
+{
+ startThreadEngine(new PrintFor(0, 40)).startBlocking();
+ QCOMPARE((int)iterations, 40);
+}
+
+void tst_QtConcurrentIterateKernel::cancel()
+{
+ {
+ QFuture<void> f = startThreadEngine(new SleepPrintFor(0, 40)).startAsynchronously();
+ f.cancel();
+ f.waitForFinished();
+ QVERIFY(f.isCanceled());
+ QVERIFY(int(iterations) <= QThread::idealThreadCount()); // the threads might run one iteration each before they are canceled.
+ }
+}
+
+QAtomicInt counter;
+class CountFor : public IterateKernel<TestIterator, void>
+{
+public:
+ CountFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) {iterations = 0; }
+ inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
+ {
+ counter.fetchAndAddRelaxed(end - begin);
+ return false;
+ }
+ bool runIteration(TestIterator it, int index , void *result)
+ {
+ return runIterations(it, index, index + 1, result);
+ }
+};
+
+void tst_QtConcurrentIterateKernel::stresstest()
+{
+ const int iterations = 1000;
+ const int times = 50;
+ for (int i = 0; i < times; ++i) {
+ counter = 0;
+ CountFor f(0, iterations);
+ f.startBlocking();
+ QCOMPARE((int)counter, iterations);
+ }
+}
+
+void tst_QtConcurrentIterateKernel::noIterations()
+{
+ const int times = 20000;
+ for (int i = 0; i < times; ++i)
+ startThreadEngine(new IterateKernel<TestIterator, void>(0, 0)).startBlocking();
+}
+
+QMutex threadsMutex;
+QSet<QThread *> threads;
+class ThrottleFor : public IterateKernel<TestIterator, void>
+{
+public:
+ // this class throttles between iterations 100 and 200,
+ // and then records how many threads that run between
+ // iterations 140 and 160.
+ ThrottleFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) {iterations = 0; throttling = false; }
+ inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
+ {
+ if (200 >= begin && 200 < end) {
+ throttling = false;
+ }
+
+ iterations.fetchAndAddRelaxed(end - begin);
+
+ QThread *thread = QThread::currentThread();
+
+ if (begin > 140 && end < 160) {
+ QMutexLocker locker(&threadsMutex);
+ threads.insert(thread);
+ }
+
+ if (100 >= begin && 100 < end) {
+ throttling = true;
+ }
+
+ QTest::qWait(1);
+
+ return false;
+ }
+ bool runIteration(TestIterator it, int index , void *result)
+ {
+ return runIterations(it, index, index + 1, result);
+ }
+
+ bool shouldThrottleThread()
+ {
+ return (iterations > 100 && iterations < 200);
+ }
+ bool throttling;
+};
+
+void tst_QtConcurrentIterateKernel::throttling()
+{
+ const int totalIterations = 400;
+ iterations = 0;
+
+ threads.clear();
+
+ ThrottleFor f(0, totalIterations);
+ f.startBlocking();
+
+ QCOMPARE((int)iterations, totalIterations);
+
+
+ QCOMPARE(threads.count(), 1);
+}
+
+
+int peakBlockSize = 0;
+class BlockSizeRecorder : public IterateKernel<TestIterator, void>
+{
+public:
+ BlockSizeRecorder(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { }
+ inline bool runIterations(TestIterator, int begin, int end, void *)
+ {
+ peakBlockSize = qMax(peakBlockSize, end - begin);
+ return false;
+ }
+};
+
+void tst_QtConcurrentIterateKernel::blockSize()
+{
+#ifdef QT_NO_STL
+ QSKIP("Missing stl iterators prevent correct block size calculation", SkipAll);
+#endif
+ const int expectedMinimumBlockSize = 1024 / QThread::idealThreadCount();
+ BlockSizeRecorder(0, 10000).startBlocking();
+ if (peakBlockSize < expectedMinimumBlockSize)
+ qDebug() << "block size" << peakBlockSize;
+ QVERIFY(peakBlockSize >= expectedMinimumBlockSize);
+}
+
+class MultipleResultsFor : public IterateKernel<TestIterator, int>
+{
+public:
+ MultipleResultsFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, int>(begin, end) { }
+ inline bool runIterations(TestIterator, int begin, int end, int *results)
+ {
+ for (int i = begin; i < end; ++i)
+ results[i - begin] = i;
+ return true;
+ }
+};
+
+
+void tst_QtConcurrentIterateKernel::multipleResults()
+{
+#ifdef QT_NO_STL
+ QSKIP("Missing stl iterators prevent correct summation", SkipAll);
+#endif
+ QFuture<int> f = startThreadEngine(new MultipleResultsFor(0, 10)).startAsynchronously();
+ QCOMPARE(f.results().count() , 10);
+ QCOMPARE(f.resultAt(0), 0);
+ QCOMPARE(f.resultAt(5), 5);
+ QCOMPARE(f.resultAt(9), 9);
+ f.waitForFinished();
+}
+
+#if 0
+class PrintWhile : public IterateKernel<TestIterator, void>
+{
+public:
+ PrintWhile() : IterateKernel<TestIterator, void>(0, 10, WhileIteration) { }
+ bool runIteration(TestIterator it, TestIterator, void *)
+ {
+ return false;
+ }
+};
+
+void tst_QtConcurrentIterateKernel::instantiateWhile()
+{
+ PrintWhile w;
+ w.startBlocking();
+}
+
+QAtomicInt iterationCount;
+class StressWhile : public IterateKernel<TestIterator, void>
+{
+public:
+ StressWhile(TestIterator iterations) : IterateKernel<TestIterator, void>(0, iterations, WhileIteration) { }
+ bool runIteration(TestIterator it, TestIterator index, void *)
+ {
+ if (it == index) // should match.
+ ::iterationCount.ref();
+ return false;
+ }
+};
+
+void tst_QtConcurrentIterateKernel::stresstestWhile()
+{
+ int iterations = 100000;
+ StressWhile w(iterations);
+ w.startBlocking();
+ QCOMPARE(int(iterationCount), iterations);
+}
+#endif
+
+QTEST_MAIN(tst_QtConcurrentIterateKernel)
+
+#include "tst_qtconcurrentiteratekernel.moc"
+
+#else
+QTEST_NOOP_MAIN
+#endif
diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore
new file mode 100644
index 0000000000..f1c563e979
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore
@@ -0,0 +1 @@
+tst_qtconcurrentmap
diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/functions.h b/tests/auto/corelib/concurrent/qtconcurrentmap/functions.h
new file mode 100644
index 0000000000..a3dcd3c300
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentmap/functions.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef FUNCTIONS_H
+#define FUNCTIONS_H
+
+bool keepEvenIntegers(const int &x)
+{
+ return (x & 1) == 0;
+}
+
+class KeepEvenIntegers
+{
+public:
+ bool operator()(const int &x)
+ {
+ return (x & 1) == 0;
+ }
+};
+
+class Number
+{
+ int n;
+
+public:
+ Number()
+ : n(0)
+ { }
+
+ Number(int n)
+ : n(n)
+ { }
+
+ void multiplyBy2()
+ {
+ n *= 2;
+ }
+
+ Number multipliedBy2() const
+ {
+ return n * 2;
+ }
+
+ bool isEven() const
+ {
+ return (n & 1) == 0;
+ }
+
+ int toInt() const
+ {
+ return n;
+ }
+
+ QString toString() const
+ {
+ return QString::number(n);
+ }
+
+ bool operator==(const Number &other) const
+ {
+ return n == other.n;
+ }
+};
+
+void intSumReduce(int &sum, int x)
+{
+ sum += x;
+}
+
+class IntSumReduce
+{
+public:
+ void operator()(int &sum, int x)
+ {
+ sum += x;
+ }
+};
+
+void numberSumReduce(int &sum, const Number &x)
+{
+ sum += x.toInt();
+}
+
+class NumberSumReduce
+{
+public:
+ void operator()(int &sum, const Number &x)
+ {
+ sum += x.toInt();
+ }
+};
+
+#endif
diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro b/tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro
new file mode 100644
index 0000000000..6fc358514e
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+DEFINES += QT_STRICT_ITERATORS
+SOURCES += tst_qtconcurrentmap.cpp
+QT = core
+CONFIG += parallel_test
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
new file mode 100644
index 0000000000..74a254cbf4
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
@@ -0,0 +1,2448 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtconcurrentmap.h>
+#include <qtconcurrentexception.h>
+
+#include <qdebug.h>
+#include <QThread>
+
+#include <QtTest/QtTest>
+
+#include "functions.h"
+#include "../qfuture/versioncheck.h"
+
+Q_DECLARE_METATYPE(QVector<int>);
+Q_DECLARE_METATYPE(QVector<double>);
+Q_DECLARE_METATYPE(QVector<QString>);
+Q_DECLARE_METATYPE(QList<int>);
+Q_DECLARE_METATYPE(QList<double>);
+Q_DECLARE_METATYPE(QList<QString>);
+
+class tst_QtConcurrentMap: public QObject
+{
+ Q_OBJECT
+private slots:
+ void map();
+ void blocking_map();
+ void mapped();
+ void blocking_mapped();
+ void mappedReduced();
+ void blocking_mappedReduced();
+ void assignResult();
+ void functionOverloads();
+#ifndef QT_NO_EXCEPTIONS
+ void exceptions();
+#endif
+ void incrementalResults();
+ void noDetatch();
+ void stlContainers();
+ void qFutureAssignmentLeak();
+ void stressTest();
+public slots:
+ void throttling();
+};
+
+#if !defined (QT_NO_CONCURRENT_TEST) && !defined(QT_NO_CONCURRENT_MAP)
+
+using namespace QtConcurrent;
+
+void multiplyBy2Immutable(int x)
+{
+ x *= 2;
+}
+
+class MultiplyBy2Immutable
+{
+public:
+ void operator()(int x)
+ {
+ x *= 2;
+ }
+};
+
+void multiplyBy2InPlace(int &x)
+{
+ x *= 2;
+}
+
+class MultiplyBy2InPlace
+{
+public:
+ void operator()(int &x)
+ {
+ x *= 2;
+ }
+};
+
+Q_DECLARE_METATYPE(QList<Number>);
+
+void tst_QtConcurrentMap::map()
+{
+ // functors take arguments by reference, modifying the sequence in place
+ {
+ QList<int> list;
+ list << 1 << 2 << 3;
+
+ // functor
+ QtConcurrent::map(list, MultiplyBy2InPlace()).waitForFinished();
+ QCOMPARE(list, QList<int>() << 2 << 4 << 6);
+ QtConcurrent::map(list.begin(), list.end(), MultiplyBy2InPlace()).waitForFinished();
+ QCOMPARE(list, QList<int>() << 4 << 8 << 12);
+
+ // function
+ QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QList<int>() << 8 << 16 << 24);
+ QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QList<int>() << 16 << 32 << 48);
+
+ // bound function
+ QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QList<int>() << 32 << 64 << 96);
+ QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QList<int>() << 64 << 128 << 192);
+
+ // member function
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QtConcurrent::map(numberList, &Number::multiplyBy2).waitForFinished();
+ QCOMPARE(numberList, QList<Number>() << 2 << 4 << 6);
+ QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished();
+ QCOMPARE(numberList, QList<Number>() << 4 << 8 << 12);
+
+#ifdef Q_COMPILER_LAMBDA
+ // lambda
+ QtConcurrent::map(list, [](int &x){x *= 2;}).waitForFinished();
+ QCOMPARE(list, QList<int>() << 128 << 256 << 384);
+ QtConcurrent::map(list.begin(), list.end(), [](int &x){x *= 2;}).waitForFinished();
+ QCOMPARE(list, QList<int>() << 256 << 512 << 768);
+#endif
+
+ }
+
+ // functors don't take arguments by reference, making these no-ops
+ {
+ QList<int> list;
+ list << 1 << 2 << 3;
+
+ // functor
+ QtConcurrent::map(list, MultiplyBy2Immutable()).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QtConcurrent::map(list.begin(), list.end(), MultiplyBy2Immutable()).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ // function
+ QtConcurrent::map(list, multiplyBy2Immutable).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ // bound function
+ QtConcurrent::map(list, multiplyBy2Immutable).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+#ifdef Q_COMPILER_LAMBDA
+ // lambda
+ QtConcurrent::map(list, [](int x){x *= 2;}).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QtConcurrent::map(list.begin(), list.end(), [](int x){x *= 2;}).waitForFinished();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+#endif
+ }
+
+ // Linked lists and forward iterators
+ {
+ QLinkedList<int> list;
+ list << 1 << 2 << 3;
+
+ // functor
+ QtConcurrent::map(list, MultiplyBy2InPlace()).waitForFinished();
+ QCOMPARE(list, QLinkedList<int>() << 2 << 4 << 6);
+ QtConcurrent::map(list.begin(), list.end(), MultiplyBy2InPlace()).waitForFinished();
+ QCOMPARE(list, QLinkedList<int>() << 4 << 8 << 12);
+
+ // function
+ QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QLinkedList<int>() << 8 << 16 << 24);
+ QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QLinkedList<int>() << 16 << 32 << 48);
+
+ // bound function
+ QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QLinkedList<int>() << 32 << 64 << 96);
+ QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished();
+ QCOMPARE(list, QLinkedList<int>() << 64 << 128 << 192);
+
+ // member function
+ QLinkedList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QtConcurrent::map(numberList, &Number::multiplyBy2).waitForFinished();
+ QCOMPARE(numberList, QLinkedList<Number>() << 2 << 4 << 6);
+ QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished();
+ QCOMPARE(numberList, QLinkedList<Number>() << 4 << 8 << 12);
+ }
+
+#if 0
+ // not allowed: map() with immutable sequences makes no sense
+ {
+ const QList<int> list = QList<int>() << 1 << 2 << 3;
+
+ QtConcurrent::map(list, MultiplyBy2Immutable());
+ QtConcurrent::map(list, multiplyBy2Immutable);
+ QtConcurrent::map(list, multiplyBy2Immutable);
+ }
+#endif
+
+#if 0
+ // not allowed: in place modification of a temp copy (since temp copy goes out of scope)
+ {
+ QList<int> list;
+ list << 1 << 2 << 3;
+
+ QtConcurrent::map(QList<int>(list), MultiplyBy2InPlace());
+ QtConcurrent::map(QList<int>(list), multiplyBy2);
+ QtConcurrent::map(QList<int>(list), multiplyBy2InPlace);
+
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QtConcurrent::map(QList<Number>(numberList), &Number::multiplyBy2);
+ }
+#endif
+
+#if 0
+ // not allowed: map() on a const list, where functors try to modify the items in the list
+ {
+ const QList<int> list = QList<int>() << 1 << 2 << 3;;
+
+ QtConcurrent::map(list, MultiplyBy2InPlace());
+ QtConcurrent::map(list, multiplyBy2InPlace);
+ QtConcurrent::map(list, multiplyBy2InPlace);
+
+ const QList<Number> numberList = QList<Number>() << 1 << 2 << 3;
+ QtConcurrent::map(numberList, &Number::multiplyBy2);
+ }
+#endif
+}
+
+void tst_QtConcurrentMap::blocking_map()
+{
+ // functors take arguments by reference, modifying the sequence in place
+ {
+ QList<int> list;
+ list << 1 << 2 << 3;
+
+ // functor
+ QtConcurrent::blockingMap(list, MultiplyBy2InPlace());
+ QCOMPARE(list, QList<int>() << 2 << 4 << 6);
+ QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2InPlace());
+ QCOMPARE(list, QList<int>() << 4 << 8 << 12);
+
+ // function
+ QtConcurrent::blockingMap(list, multiplyBy2InPlace);
+ QCOMPARE(list, QList<int>() << 8 << 16 << 24);
+ QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace);
+ QCOMPARE(list, QList<int>() << 16 << 32 << 48);
+
+ // bound function
+ QtConcurrent::blockingMap(list, multiplyBy2InPlace);
+ QCOMPARE(list, QList<int>() << 32 << 64 << 96);
+ QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace);
+ QCOMPARE(list, QList<int>() << 64 << 128 << 192);
+
+ // member function
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QtConcurrent::blockingMap(numberList, &Number::multiplyBy2);
+ QCOMPARE(numberList, QList<Number>() << 2 << 4 << 6);
+ QtConcurrent::blockingMap(numberList.begin(), numberList.end(), &Number::multiplyBy2);
+ QCOMPARE(numberList, QList<Number>() << 4 << 8 << 12);
+ }
+
+ // functors don't take arguments by reference, making these no-ops
+ {
+ QList<int> list;
+ list << 1 << 2 << 3;
+
+ // functor
+ QtConcurrent::blockingMap(list, MultiplyBy2Immutable());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2Immutable());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ // function
+ QtConcurrent::blockingMap(list, multiplyBy2Immutable);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2Immutable);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ // bound function
+ QtConcurrent::blockingMap(list, multiplyBy2Immutable);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2Immutable);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ }
+
+ // Linked lists and forward iterators
+ {
+ QLinkedList<int> list;
+ list << 1 << 2 << 3;
+
+ // functor
+ QtConcurrent::blockingMap(list, MultiplyBy2InPlace());
+ QCOMPARE(list, QLinkedList<int>() << 2 << 4 << 6);
+ QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2InPlace());
+ QCOMPARE(list, QLinkedList<int>() << 4 << 8 << 12);
+
+ // function
+ QtConcurrent::blockingMap(list, multiplyBy2InPlace);
+ QCOMPARE(list, QLinkedList<int>() << 8 << 16 << 24);
+ QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace);
+ QCOMPARE(list, QLinkedList<int>() << 16 << 32 << 48);
+
+ // bound function
+ QtConcurrent::blockingMap(list, multiplyBy2InPlace);
+ QCOMPARE(list, QLinkedList<int>() << 32 << 64 << 96);
+ QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace);
+ QCOMPARE(list, QLinkedList<int>() << 64 << 128 << 192);
+
+ // member function
+ QLinkedList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QtConcurrent::blockingMap(numberList, &Number::multiplyBy2);
+ QCOMPARE(numberList, QLinkedList<Number>() << 2 << 4 << 6);
+ QtConcurrent::blockingMap(numberList.begin(), numberList.end(), &Number::multiplyBy2);
+ QCOMPARE(numberList, QLinkedList<Number>() << 4 << 8 << 12);
+ }
+
+#if 0
+ // not allowed: map() with immutable sequences makes no sense
+ {
+ const QList<int> list = QList<int>() << 1 << 2 << 3;
+
+ QtConcurrent::blockingMap(list, MultiplyBy2Immutable());
+ QtConcurrent::blockkng::map(list, multiplyBy2Immutable);
+ QtConcurrent::blockingMap(list, multiplyBy2Immutable);
+ }
+#endif
+
+#if 0
+ // not allowed: in place modification of a temp copy (since temp copy goes out of scope)
+ {
+ QList<int> list;
+ list << 1 << 2 << 3;
+
+ QtConcurrent::blockingMap(QList<int>(list), MultiplyBy2InPlace());
+ QtConcurrent::blockingMap(QList<int>(list), multiplyBy2);
+ QtConcurrent::blockingMap(QList<int>(list), multiplyBy2InPlace);
+
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QtConcurrent::blockingMap(QList<Number>(numberList), &Number::multiplyBy2);
+ }
+#endif
+
+#if 0
+ // not allowed: map() on a const list, where functors try to modify the items in the list
+ {
+ const QList<int> list = QList<int>() << 1 << 2 << 3;;
+
+ QtConcurrent::blockingMap(list, MultiplyBy2InPlace());
+ QtConcurrent::blockingMap(list, multiplyBy2InPlace);
+ QtConcurrent::blockingMap(list, multiplyBy2InPlace);
+
+ const QList<Number> numberList = QList<Number>() << 1 << 2 << 3;
+ QtConcurrent::blockingMap(numberList, &Number::multiplyBy2);
+ }
+#endif
+}
+
+int multiplyBy2(int x)
+{
+ int y = x * 2;
+ return y;
+}
+
+class MultiplyBy2
+{
+public:
+ typedef int result_type;
+
+ int operator()(int x) const
+ {
+ int y = x * 2;
+ return y;
+ }
+};
+
+double intToDouble(int x)
+{
+ return double(x);
+}
+
+class IntToDouble
+{
+public:
+ typedef double result_type;
+
+ double operator()(int x) const
+ {
+ return double(x);
+ }
+};
+
+int stringToInt(const QString &string)
+{
+ return string.toInt();
+}
+
+class StringToInt
+{
+public:
+ typedef int result_type;
+
+ int operator()(const QString &string) const
+ {
+ return string.toInt();
+ }
+};
+
+void tst_QtConcurrentMap::mapped()
+{
+ QList<int> list;
+ list << 1 << 2 << 3;
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3;
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QLinkedList<Number> numberLinkedList;
+ numberLinkedList << 1 << 2 << 3;
+
+ // functor
+ {
+ QList<int> list2 = QtConcurrent::mapped(list, MultiplyBy2()).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::mapped(list.constBegin(),
+ list.constEnd(),
+ MultiplyBy2()).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 = QtConcurrent::mapped(QList<int>(list), MultiplyBy2()).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+ {
+ QList<int> list2 = QtConcurrent::mapped(linkedList, MultiplyBy2()).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::mapped(linkedList.constBegin(),
+ linkedList.constEnd(),
+ MultiplyBy2()).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 =
+ QtConcurrent::mapped(QLinkedList<int>(linkedList), MultiplyBy2()).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+
+ // function
+ {
+ QList<int> list2 = QtConcurrent::mapped(list, multiplyBy2).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::mapped(list.constBegin(),
+ list.constEnd(),
+ multiplyBy2).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 = QtConcurrent::mapped(QList<int>(list), multiplyBy2).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+ {
+ QList<int> list2 = QtConcurrent::mapped(linkedList, multiplyBy2).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::mapped(linkedList.constBegin(),
+ linkedList.constEnd(),
+ multiplyBy2).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 =
+ QtConcurrent::mapped(QLinkedList<int>(linkedList), multiplyBy2).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+
+ // bound function
+ {
+ QList<int> list2 = QtConcurrent::mapped(list, multiplyBy2).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::mapped(list.constBegin(),
+ list.constEnd(),
+ multiplyBy2).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 = QtConcurrent::mapped(QList<int>(list), multiplyBy2).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+ {
+ QList<int> list2 = QtConcurrent::mapped(linkedList, multiplyBy2).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::mapped(linkedList.constBegin(),
+ linkedList.constEnd(),
+ multiplyBy2)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 = QtConcurrent::mapped(QLinkedList<int>(linkedList), multiplyBy2)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+
+ // const member function
+ {
+ QList<Number> numberList2 = QtConcurrent::mapped(numberList, &Number::multipliedBy2)
+ .results();
+ QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList2, QList<Number>() << 2 << 4 << 6);
+
+ QList<Number> numberList3 = QtConcurrent::mapped(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::multipliedBy2)
+ .results();
+ QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList3, QList<Number>() << 2 << 4 << 6);
+
+ QList<Number> numberList4 = QtConcurrent::mapped(QList<Number>(numberList),
+ &Number::multipliedBy2)
+ .results();
+ QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList4, QList<Number>() << 2 << 4 << 6);
+ }
+ {
+ QList<Number> numberList2 = QtConcurrent::mapped(numberLinkedList, &Number::multipliedBy2)
+ .results();
+ QCOMPARE(numberLinkedList, QLinkedList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList2, QList<Number>() << 2 << 4 << 6);
+
+ QList<Number> numberList3 = QtConcurrent::mapped(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::multipliedBy2)
+ .results();
+ QCOMPARE(numberLinkedList, QLinkedList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList3, QList<Number>() << 2 << 4 << 6);
+
+ QList<Number> numberList4 = QtConcurrent::mapped(QLinkedList<Number>(numberLinkedList),
+ &Number::multipliedBy2)
+ .results();
+ QCOMPARE(numberLinkedList, QLinkedList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList4, QList<Number>() << 2 << 4 << 6);
+ }
+
+ // change the value_type, same container
+
+ // functor
+ {
+ QList<double> list2 = QtConcurrent::mapped(list, IntToDouble()).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::mapped(list.constBegin(),
+ list.constEnd(),
+ IntToDouble())
+ .results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list4 = QtConcurrent::mapped(QList<int>(list),
+ IntToDouble())
+ .results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+ {
+ QList<double> list2 = QtConcurrent::mapped(linkedList, IntToDouble()).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::mapped(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntToDouble())
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list4 = QtConcurrent::mapped(QLinkedList<int>(linkedList),
+ IntToDouble())
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+
+ // function
+ {
+ QList<double> list2 = QtConcurrent::mapped(list, intToDouble).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::mapped(list.constBegin(),
+ list.constEnd(),
+ intToDouble)
+ .results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list4 = QtConcurrent::mapped(QList<int>(list), intToDouble).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+ {
+ QList<double> list2 = QtConcurrent::mapped(linkedList, intToDouble).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::mapped(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intToDouble)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list4 = QtConcurrent::mapped(QLinkedList<int>(linkedList), intToDouble)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+
+ // bound function
+ {
+ QList<double> list2 = QtConcurrent::mapped(list, intToDouble).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::mapped(list.constBegin(),
+ list.constEnd(),
+ intToDouble)
+ .results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+
+ QList<double> list4 = QtConcurrent::mapped(QList<int>(list),
+ intToDouble)
+ .results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+ {
+ QList<double> list2 = QtConcurrent::mapped(linkedList, intToDouble).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::mapped(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intToDouble)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+
+ QList<double> list4 = QtConcurrent::mapped(QLinkedList<int>(linkedList),
+ intToDouble)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+
+ // const member function
+ {
+ QList<QString> list2 = QtConcurrent::mapped(numberList, &Number::toString).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<QString>() << "1" << "2" << "3");
+
+ QList<QString> list3 = QtConcurrent::mapped(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toString)
+ .results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<QString>() << "1" << "2" << "3");
+
+ QList<QString> list4 = QtConcurrent::mapped(QList<Number>(numberList), &Number::toString)
+ .results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<QString>() << "1" << "2" << "3");
+ }
+ {
+ QList<QString> list2 = QtConcurrent::mapped(numberLinkedList, &Number::toString).results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<QString>() << "1" << "2" << "3");
+
+ QList<QString> list3 = QtConcurrent::mapped(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::toString)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<QString>() << "1" << "2" << "3");
+
+ QList<QString> list4 = QtConcurrent::mapped(QLinkedList<Number>(numberLinkedList),
+ &Number::toString)
+ .results();
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<QString>() << "1" << "2" << "3");
+ }
+
+ // change the value_type
+ {
+ QList<QString> strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::mapped(strings, StringToInt()).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::mapped(strings.constBegin(),
+ strings.constEnd(),
+ StringToInt())
+ .results();
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+ {
+ QList<QString> strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::mapped(strings, stringToInt).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::mapped(strings.constBegin(),
+ strings.constEnd(),
+ stringToInt).results();
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+
+ {
+ QList<int> numberList2 = QtConcurrent::mapped(numberList, &Number::toInt).results();
+ QCOMPARE(numberList2, QList<int>() << 1 << 2 << 3);
+
+ QList<int> numberList3 = QtConcurrent::mapped(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt)
+ .results();
+ QCOMPARE(numberList3, QList<int>() << 1 << 2 << 3);
+ }
+
+ // change the value_type from QStringList
+ {
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::mapped(strings, StringToInt()).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::mapped(strings.constBegin(),
+ strings.constEnd(),
+ StringToInt())
+ .results();
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+ {
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::mapped(strings, stringToInt).results();
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::mapped(strings.constBegin(),
+ strings.constEnd(),
+ stringToInt)
+ .results();
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+}
+
+void tst_QtConcurrentMap::blocking_mapped()
+{
+ QList<int> list;
+ list << 1 << 2 << 3;
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3;
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QLinkedList<Number> numberLinkedList;
+ numberLinkedList << 1 << 2 << 3;
+
+ // functor
+ {
+ QList<int> list2 = QtConcurrent::blockingMapped(list, MultiplyBy2());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::blockingMapped<QList<int> >(list.constBegin(),
+ list.constEnd(),
+ MultiplyBy2());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 = QtConcurrent::blockingMapped(QList<int>(list), MultiplyBy2());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingMapped(linkedList, MultiplyBy2());
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4 << 6);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::blockingMapped<QLinkedList<int> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ MultiplyBy2());
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 2 << 4 << 6);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::blockingMapped(QLinkedList<int>(linkedList), MultiplyBy2());
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 2 << 4 << 6);
+ }
+
+ // function
+ {
+ QList<int> list2 = QtConcurrent::blockingMapped(list, multiplyBy2);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::blockingMapped<QList<int> >(list.constBegin(),
+ list.constEnd(),
+ multiplyBy2);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 = QtConcurrent::blockingMapped(QList<int>(list), multiplyBy2);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingMapped(linkedList, multiplyBy2);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4 << 6);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::blockingMapped<QLinkedList<int> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ multiplyBy2);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 2 << 4 << 6);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::blockingMapped(QLinkedList<int>(linkedList), multiplyBy2);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 2 << 4 << 6);
+ }
+
+ // bound function
+ {
+ QList<int> list2 = QtConcurrent::blockingMapped(list, multiplyBy2);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list3 = QtConcurrent::blockingMapped<QList<int> >(list.constBegin(),
+ list.constEnd(),
+ multiplyBy2);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 2 << 4 << 6);
+
+ QList<int> list4 = QtConcurrent::blockingMapped(QList<int>(list), multiplyBy2);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 2 << 4 << 6);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingMapped(linkedList, multiplyBy2);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 2 << 4 << 6);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::blockingMapped<QLinkedList<int> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ multiplyBy2);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 2 << 4 << 6);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::blockingMapped(QLinkedList<int>(linkedList), multiplyBy2);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 2 << 4 << 6);
+ }
+
+ // const member function
+ {
+ QList<Number> numberList2 = QtConcurrent::blockingMapped(numberList, &Number::multipliedBy2);
+ QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList2, QList<Number>() << 2 << 4 << 6);
+
+ QList<Number> numberList3 = QtConcurrent::blockingMapped<QList<Number> >(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::multipliedBy2);
+ QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList3, QList<Number>() << 2 << 4 << 6);
+
+ QList<Number> numberList4 = QtConcurrent::blockingMapped(QList<Number>(numberList),
+ &Number::multipliedBy2);
+ QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberList4, QList<Number>() << 2 << 4 << 6);
+ }
+ {
+ QLinkedList<Number> numberLinkedList2 = QtConcurrent::blockingMapped(numberLinkedList, &Number::multipliedBy2);
+ QCOMPARE(numberLinkedList, QLinkedList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberLinkedList2, QLinkedList<Number>() << 2 << 4 << 6);
+
+ QLinkedList<Number> numberLinkedList3 = QtConcurrent::blockingMapped<QLinkedList<Number> >(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::multipliedBy2);
+ QCOMPARE(numberLinkedList, QLinkedList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberLinkedList3, QLinkedList<Number>() << 2 << 4 << 6);
+
+ QLinkedList<Number> numberLinkedList4 = QtConcurrent::blockingMapped(QLinkedList<Number>(numberLinkedList),
+ &Number::multipliedBy2);
+ QCOMPARE(numberLinkedList, QLinkedList<Number>() << 1 << 2 << 3);
+ QCOMPARE(numberLinkedList4, QLinkedList<Number>() << 2 << 4 << 6);
+ }
+
+ // change the value_type, same container
+
+ // functor
+ {
+ QList<double> list2 = QtConcurrent::blockingMapped<QList<double> >(list, IntToDouble());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::blockingMapped<QList<double> >(list.constBegin(),
+ list.constEnd(),
+ IntToDouble());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list4 = QtConcurrent::blockingMapped<QList<double> >(QList<int>(list),
+ IntToDouble());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+ {
+ QLinkedList<double> linkedList2 = QtConcurrent::blockingMapped<QLinkedList<double> >(linkedList, IntToDouble());
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+
+ QLinkedList<double> linkedList3 = QtConcurrent::blockingMapped<QLinkedList<double> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntToDouble());
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+
+ QLinkedList<double> linkedList4 = QtConcurrent::blockingMapped<QLinkedList<double> >(QLinkedList<int>(linkedList),
+ IntToDouble());
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+ }
+
+ // function
+ {
+ QList<double> list2 = QtConcurrent::blockingMapped<QList<double> >(list, intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::blockingMapped<QList<double> >(list.constBegin(),
+ list.constEnd(),
+ intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list4 = QtConcurrent::blockingMapped<QList<double> >(QList<int>(list), intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+ {
+ QLinkedList<double> linkedList2 = QtConcurrent::blockingMapped<QLinkedList<double> >(linkedList, intToDouble);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+
+ QLinkedList<double> linkedList3 = QtConcurrent::blockingMapped<QLinkedList<double> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intToDouble);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+
+ QLinkedList<double> linkedList4 = QtConcurrent::blockingMapped<QLinkedList<double> >(QLinkedList<int>(linkedList), intToDouble);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+ }
+
+ // bound function
+ {
+ QList<double> list2 = QtConcurrent::blockingMapped<QList<double> >(list, intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0);
+
+ QList<double> list3 = QtConcurrent::blockingMapped<QList<double> >(list.constBegin(),
+ list.constEnd(),
+ intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0);
+
+
+ QList<double> list4 = QtConcurrent::blockingMapped<QList<double> >(QList<int>(list),
+ intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0);
+ }
+ {
+ QLinkedList<double> linkedList2 = QtConcurrent::blockingMapped<QLinkedList<double> >(linkedList, intToDouble);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+
+ QLinkedList<double> linkedList3 = QtConcurrent::blockingMapped<QLinkedList<double> >(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intToDouble);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+
+
+ QLinkedList<double> linkedList4 = QtConcurrent::blockingMapped<QLinkedList<double> >(QLinkedList<int>(linkedList),
+ intToDouble);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<double>() << 1.0 << 2.0 << 3.0);
+ }
+
+ // const member function
+ {
+ QList<QString> list2 =
+ QtConcurrent::blockingMapped<QList<QString> >(numberList, &Number::toString);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<QString>() << "1" << "2" << "3");
+
+ QList<QString> list3 = QtConcurrent::blockingMapped<QList<QString> >(numberList.constBegin(),
+ numberList.constEnd()
+ , &Number::toString);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<QString>() << "1" << "2" << "3");
+
+ QList<QString> list4 =
+ QtConcurrent::blockingMapped<QList<QString> >(QList<Number>(numberList), &Number::toString);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<QString>() << "1" << "2" << "3");
+ }
+ {
+ QLinkedList<QString> linkedList2 =
+ QtConcurrent::blockingMapped<QLinkedList<QString> >(numberLinkedList, &Number::toString);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<QString>() << "1" << "2" << "3");
+
+ QLinkedList<QString> linkedList3 = QtConcurrent::blockingMapped<QLinkedList<QString> >(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd()
+ , &Number::toString);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<QString>() << "1" << "2" << "3");
+
+ QLinkedList<QString> linkedList4 =
+ QtConcurrent::blockingMapped<QLinkedList<QString> >(QLinkedList<Number>(numberLinkedList), &Number::toString);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<QString>() << "1" << "2" << "3");
+ }
+
+ // change the value_type
+ {
+ QList<QString> strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::blockingMapped(strings, StringToInt());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::blockingMapped<QList<int> >(strings.constBegin(),
+ strings.constEnd(),
+ StringToInt());
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+ {
+ QList<QString> strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::blockingMapped(strings, stringToInt);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::blockingMapped<QList<int> >(strings.constBegin(),
+ strings.constEnd(),
+ stringToInt);
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+
+ {
+ QList<int> numberList2 = QtConcurrent::blockingMapped(numberList, &Number::toInt);
+ QCOMPARE(numberList2, QList<int>() << 1 << 2 << 3);
+
+ QList<int> numberList3 = QtConcurrent::blockingMapped<QList<int> >(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt);
+ QCOMPARE(numberList3, QList<int>() << 1 << 2 << 3);
+ }
+
+ // change the value_type from QStringList
+ {
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::blockingMapped(strings, StringToInt());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::blockingMapped<QList<int> >(strings.constBegin(),
+ strings.constEnd(),
+ StringToInt());
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+ {
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QList<int> list = QtConcurrent::blockingMapped(strings, stringToInt);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list2 = QtConcurrent::blockingMapped<QList<int> >(strings.constBegin(),
+ strings.constEnd(),
+ stringToInt);
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+ }
+
+ // functor
+ {
+ QVector<double> list2 = QtConcurrent::blockingMapped<QVector<double> >(list, IntToDouble());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QVector<double> list3 = QtConcurrent::blockingMapped<QVector<double> >(list.constBegin(),
+ list.constEnd(),
+ IntToDouble());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QVector<double> list4 = QtConcurrent::blockingMapped<QVector<double> >(QList<int>(list),
+ IntToDouble());
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QVector<int> list5 = QtConcurrent::blockingMapped<QVector<int> >(strings, StringToInt());
+ QCOMPARE(list5, QVector<int>() << 1 << 2 << 3);
+
+ QVector<int> list6 = QtConcurrent::blockingMapped<QVector<int> >(strings.constBegin(),
+ strings.constEnd(),
+ StringToInt());
+ QCOMPARE(list6, QVector<int>() << 1 << 2 << 3);
+
+ QVector<int> list7 = QtConcurrent::blockingMapped<QVector<int> >(QStringList(strings),
+ StringToInt());
+ QCOMPARE(list7, QVector<int>() << 1 << 2 << 3);
+ }
+
+ // function
+ {
+ QVector<double> list2 = QtConcurrent::blockingMapped<QVector<double> >(list, intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QVector<double> list3 = QtConcurrent::blockingMapped<QVector<double> >(list.constBegin(),
+ list.constEnd(),
+ intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QVector<double> list4 = QtConcurrent::blockingMapped<QVector<double> >(QList<int>(list),
+ intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QVector<int> list5 = QtConcurrent::blockingMapped<QVector<int> >(strings, stringToInt);
+ QCOMPARE(list5, QVector<int>() << 1 << 2 << 3);
+
+ QVector<int> list6 = QtConcurrent::blockingMapped<QVector<int> >(strings.constBegin(),
+ strings.constEnd(),
+ stringToInt);
+ QCOMPARE(list6, QVector<int>() << 1 << 2 << 3);
+
+ QVector<int> list7 = QtConcurrent::blockingMapped<QVector<int> >(QStringList(strings),
+ stringToInt);
+ QCOMPARE(list7, QVector<int>() << 1 << 2 << 3);
+ }
+
+ // bound function
+ {
+ QVector<double> list2 = QtConcurrent::blockingMapped<QVector<double> >(list, intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QVector<double> list3 = QtConcurrent::blockingMapped<QVector<double> >(QList<int>(list), intToDouble);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QVector<double>() << 1.0 << 2.0 << 3.0);
+
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QVector<int> list4 = QtConcurrent::blockingMapped<QVector<int> >(strings, stringToInt);
+ QCOMPARE(list4, QVector<int>() << 1 << 2 << 3);
+
+ QVector<int> list5 = QtConcurrent::blockingMapped<QVector<int> >(QStringList(strings), stringToInt);
+ QCOMPARE(list5, QVector<int>() << 1 << 2 << 3);
+ }
+
+ // const member function
+ {
+ QVector<QString> list2 = QtConcurrent::blockingMapped<QVector<QString> >(numberList, &Number::toString);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QVector<QString>() << "1" << "2" << "3");
+
+ QVector<QString> list3 =
+ QtConcurrent::blockingMapped<QVector<QString> >(QList<Number>(numberList), &Number::toString);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QVector<QString>() << "1" << "2" << "3");
+
+ // not allowed: const member function where all arguments have default values
+#if 0
+ QStringList strings = QStringList() << "1" << "2" << "3";
+ QVector<int> list4 = QtConcurrent::blockingMapped<QVector<int> >(strings, &QString::toInt);
+ QCOMPARE(list4, QVector<int>() << 1 << 2 << 3);
+
+ QVector<int> list5 = QtConcurrent::blockingMapped<QVector<int> >(QStringList(strings), &QString::toInt);
+ QCOMPARE(list5, QVector<int>() << 1 << 2 << 3);
+#endif
+ }
+}
+
+int intSquare(int x)
+{
+ return x * x;
+}
+
+class IntSquare
+{
+public:
+ typedef int result_type;
+
+ int operator()(int x)
+ {
+ return x * x;
+ }
+};
+
+void tst_QtConcurrentMap::mappedReduced()
+{
+ QList<int> list;
+ list << 1 << 2 << 3;
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3;
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QLinkedList<Number> numberLinkedList;
+ numberLinkedList << 1 << 2 << 3;
+
+ // test Q_DECLARE_OPERATORS_FOR_FLAGS
+ QtConcurrent::ReduceOptions opt = (QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce);
+
+ // functor-functor
+ {
+ int sum = QtConcurrent::mappedReduced<int>(list, IntSquare(), IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced<int>(QList<int>(list), IntSquare(), IntSumReduce());
+ QCOMPARE(sum3, 14);
+
+ int sum4 = QtConcurrent::mappedReduced<int>(list, intSquare, intSumReduce);
+ QCOMPARE(sum4, 14);
+ int sum5 = QtConcurrent::mappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum5, 14);
+
+ int sum6 = QtConcurrent::mappedReduced<int>(QList<int>(list),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum6, 14);
+ }
+ {
+ int sum = QtConcurrent::mappedReduced<int>(linkedList, IntSquare(), IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntSquare(),
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced<int>(QLinkedList<int>(linkedList), IntSquare(), IntSumReduce());
+ QCOMPARE(sum3, 14);
+
+ int sum4 = QtConcurrent::mappedReduced<int>(linkedList, intSquare, intSumReduce);
+ QCOMPARE(sum4, 14);
+ int sum5 = QtConcurrent::mappedReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum5, 14);
+
+ int sum6 = QtConcurrent::mappedReduced<int>(QLinkedList<int>(linkedList),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum6, 14);
+ }
+
+ // function-functor
+ {
+ int sum = QtConcurrent::mappedReduced<int>(list, intSquare, IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced<int>(QList<int>(list), intSquare, IntSumReduce());
+ QCOMPARE(sum3, 14);
+ }
+ {
+ int sum = QtConcurrent::mappedReduced<int>(linkedList, intSquare, IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced<int>(QLinkedList<int>(linkedList), intSquare, IntSumReduce());
+ QCOMPARE(sum3, 14);
+ }
+
+ // functor-function
+ {
+ int sum = QtConcurrent::mappedReduced(list, IntSquare(), intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced(QList<int>(list), IntSquare(), intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+ {
+ int sum = QtConcurrent::mappedReduced(linkedList, IntSquare(), intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntSquare(),
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced(QLinkedList<int>(linkedList), IntSquare(), intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+
+ // function-function
+ {
+ int sum = QtConcurrent::mappedReduced(list, intSquare, intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced(QList<int>(list), intSquare, intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+ {
+ int sum = QtConcurrent::mappedReduced(linkedList, intSquare, intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced(QLinkedList<int>(linkedList), intSquare, intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+
+ // functor-member
+ {
+ QList<int> list2 = QtConcurrent::mappedReduced(list,
+ IntSquare(),
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list3 = QtConcurrent::mappedReduced(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list4 = QtConcurrent::mappedReduced(QList<int>(list),
+ IntSquare(),
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 1 << 4 << 9);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::mappedReduced(linkedList,
+ IntSquare(),
+ &QLinkedList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::mappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntSquare(),
+ &QLinkedList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::mappedReduced(QLinkedList<int>(linkedList),
+ IntSquare(),
+ &QLinkedList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 1 << 4 << 9);
+ }
+
+ // member-functor
+ {
+ int sum = QtConcurrent::mappedReduced<int>(numberList, &Number::toInt, IntSumReduce());
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::mappedReduced<int>(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::mappedReduced<int>(QList<Number>(numberList),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum3, 6);
+ }
+ {
+ int sum = QtConcurrent::mappedReduced<int>(numberLinkedList, &Number::toInt, IntSumReduce());
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::mappedReduced<int>(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::mappedReduced<int>(QLinkedList<Number>(numberLinkedList),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum3, 6);
+ }
+
+ // member-member
+ {
+ QList<int> list2 = QtConcurrent::mappedReduced(numberList,
+ &Number::toInt,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list3 = QtConcurrent::mappedReduced(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list3, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list4 = QtConcurrent::mappedReduced(QList<Number>(numberList),
+ &Number::toInt,
+ &QList<int>::push_back, OrderedReduce);
+ QCOMPARE(list4, QList<int>() << 1 << 2 << 3);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::mappedReduced(numberLinkedList,
+ &Number::toInt,
+ &QLinkedList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 1 << 2 << 3);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::toInt,
+ &QLinkedList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 1 << 2 << 3);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::mappedReduced(QLinkedList<Number>(numberLinkedList),
+ &Number::toInt,
+ &QLinkedList<int>::push_back, OrderedReduce);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 1 << 2 << 3);
+ }
+
+ // function-member
+ {
+ QList<int> list2 = QtConcurrent::mappedReduced(list,
+ intSquare,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list3 = QtConcurrent::mappedReduced(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list4 = QtConcurrent::mappedReduced(QList<int>(list),
+ intSquare,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 1 << 4 << 9);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::mappedReduced(linkedList,
+ intSquare,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::mappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::mappedReduced(QLinkedList<int>(linkedList),
+ intSquare,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 1 << 4 << 9);
+ }
+
+ // member-function
+ {
+ int sum = QtConcurrent::mappedReduced(numberList,
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::mappedReduced(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::mappedReduced(QList<Number>(numberList),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum3, 6);
+ }
+ {
+ int sum = QtConcurrent::mappedReduced(numberLinkedList,
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::mappedReduced(QLinkedList<Number>(numberLinkedList),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum3, 6);
+ }
+
+ // linked lists
+ {
+
+ QLinkedList<int> list;
+ list << 1 << 2 << 3;
+
+ QLinkedList<Number> numberList;
+ numberList << 1 << 2 << 3;
+
+ int sum = QtConcurrent::mappedReduced<int>(list, IntSquare(), IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::mappedReduced<int>(QLinkedList<int>(list), IntSquare(), IntSumReduce());
+ QCOMPARE(sum3, 14);
+
+ int sum4 = QtConcurrent::mappedReduced<int>(list, intSquare, intSumReduce);
+ QCOMPARE(sum4, 14);
+ int sum5 = QtConcurrent::mappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum5, 14);
+
+ int sum6 = QtConcurrent::mappedReduced<int>(QLinkedList<int>(list),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum6, 14);
+ }
+
+ // ### the same as above, with an initial result value
+}
+
+void tst_QtConcurrentMap::blocking_mappedReduced()
+{
+ QList<int> list;
+ list << 1 << 2 << 3;
+ QLinkedList<int> linkedList;
+ linkedList << 1 << 2 << 3;
+ QList<Number> numberList;
+ numberList << 1 << 2 << 3;
+ QLinkedList<Number> numberLinkedList;
+ numberLinkedList << 1 << 2 << 3;
+
+ // functor-functor
+ {
+ int sum = QtConcurrent::blockingMappedReduced<int>(list, IntSquare(), IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<int>(list), IntSquare(), IntSumReduce());
+ QCOMPARE(sum3, 14);
+
+ int sum4 = QtConcurrent::blockingMappedReduced<int>(list, intSquare, intSumReduce);
+ QCOMPARE(sum4, 14);
+ int sum5 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum5, 14);
+
+ int sum6 = QtConcurrent::blockingMappedReduced<int>(QList<int>(list),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum6, 14);
+ }
+ {
+ int sum = QtConcurrent::blockingMappedReduced<int>(linkedList, IntSquare(), IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntSquare(),
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced<int>(QLinkedList<int>(linkedList), IntSquare(), IntSumReduce());
+ QCOMPARE(sum3, 14);
+
+ int sum4 = QtConcurrent::blockingMappedReduced<int>(linkedList, intSquare, intSumReduce);
+ QCOMPARE(sum4, 14);
+ int sum5 = QtConcurrent::blockingMappedReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum5, 14);
+
+ int sum6 = QtConcurrent::blockingMappedReduced<int>(QLinkedList<int>(linkedList),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum6, 14);
+ }
+
+ // function-functor
+ {
+ int sum = QtConcurrent::blockingMappedReduced<int>(list, intSquare, IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<int>(list), intSquare, IntSumReduce());
+ QCOMPARE(sum3, 14);
+ }
+ {
+ int sum = QtConcurrent::blockingMappedReduced<int>(linkedList, intSquare, IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced<int>(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced<int>(QLinkedList<int>(linkedList), intSquare, IntSumReduce());
+ QCOMPARE(sum3, 14);
+ }
+
+ // functor-function
+ {
+ int sum = QtConcurrent::blockingMappedReduced(list, IntSquare(), intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced(QList<int>(list), IntSquare(), intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+ {
+ int sum = QtConcurrent::blockingMappedReduced(linkedList, IntSquare(), intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntSquare(),
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList<int>(linkedList), IntSquare(), intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+
+ // function-function
+ {
+ int sum = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced(QList<int>(list), intSquare, intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+ {
+ int sum = QtConcurrent::blockingMappedReduced(linkedList, intSquare, intSumReduce);
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList<int>(linkedList), intSquare, intSumReduce);
+ QCOMPARE(sum3, 14);
+ }
+
+ // functor-member
+ {
+ QList<int> list2 = QtConcurrent::blockingMappedReduced(list,
+ IntSquare(),
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list3 = QtConcurrent::blockingMappedReduced(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list4 = QtConcurrent::blockingMappedReduced(QList<int>(list),
+ IntSquare(),
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 1 << 4 << 9);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingMappedReduced(linkedList,
+ IntSquare(),
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ IntSquare(),
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList<int>(linkedList),
+ IntSquare(),
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 1 << 4 << 9);
+ }
+
+ // member-functor
+ {
+ int sum = QtConcurrent::blockingMappedReduced<int>(numberList, &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::blockingMappedReduced<int>(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<Number>(numberList),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum3, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingMappedReduced<int>(numberLinkedList, &Number::toInt, IntSumReduce());
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::blockingMappedReduced<int>(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::blockingMappedReduced<int>(QLinkedList<Number>(numberLinkedList),
+ &Number::toInt,
+ IntSumReduce());
+ QCOMPARE(sum3, 6);
+ }
+
+ // member-member
+ {
+ QList<int> list2 = QtConcurrent::blockingMappedReduced(numberList,
+ &Number::toInt,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list2, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list3 = QtConcurrent::blockingMappedReduced(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list3, QList<int>() << 1 << 2 << 3);
+
+ QList<int> list4 = QtConcurrent::blockingMappedReduced(QList<Number>(numberList),
+ &Number::toInt,
+ &QList<int>::push_back, OrderedReduce);
+ QCOMPARE(list4, QList<int>() << 1 << 2 << 3);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingMappedReduced(numberLinkedList,
+ &Number::toInt,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 1 << 2 << 3);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::toInt,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 1 << 2 << 3);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList<Number>(numberLinkedList),
+ &Number::toInt,
+ &QLinkedList<int>::append, OrderedReduce);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 1 << 2 << 3);
+ }
+
+ // function-member
+ {
+ QList<int> list2 = QtConcurrent::blockingMappedReduced(list,
+ intSquare,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list2, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list3 = QtConcurrent::blockingMappedReduced(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list3, QList<int>() << 1 << 4 << 9);
+
+ QList<int> list4 = QtConcurrent::blockingMappedReduced(QList<int>(list),
+ intSquare,
+ &QList<int>::push_back,
+ OrderedReduce);
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3);
+ QCOMPARE(list4, QList<int>() << 1 << 4 << 9);
+ }
+ {
+ QLinkedList<int> linkedList2 = QtConcurrent::blockingMappedReduced(linkedList,
+ intSquare,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList2, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList3 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(),
+ linkedList.constEnd(),
+ intSquare,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList3, QLinkedList<int>() << 1 << 4 << 9);
+
+ QLinkedList<int> linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList<int>(linkedList),
+ intSquare,
+ &QLinkedList<int>::append,
+ OrderedReduce);
+ QCOMPARE(linkedList, QLinkedList<int>() << 1 << 2 << 3);
+ QCOMPARE(linkedList4, QLinkedList<int>() << 1 << 4 << 9);
+ }
+
+ // member-function
+ {
+ int sum = QtConcurrent::blockingMappedReduced(numberList,
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::blockingMappedReduced(numberList.constBegin(),
+ numberList.constEnd(),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::blockingMappedReduced(QList<Number>(numberList),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum3, 6);
+ }
+ {
+ int sum = QtConcurrent::blockingMappedReduced(numberLinkedList,
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum, 6);
+ int sum2 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(),
+ numberLinkedList.constEnd(),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum2, 6);
+
+ int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList<Number>(numberLinkedList),
+ &Number::toInt,
+ intSumReduce);
+ QCOMPARE(sum3, 6);
+ }
+
+ // linked lists
+ {
+
+ QLinkedList<int> list;
+ list << 1 << 2 << 3;
+
+ QLinkedList<Number> numberList;
+ numberList << 1 << 2 << 3;
+
+ int sum = QtConcurrent::blockingMappedReduced<int>(list, IntSquare(), IntSumReduce());
+ QCOMPARE(sum, 14);
+ int sum2 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ IntSquare(),
+ IntSumReduce());
+ QCOMPARE(sum2, 14);
+
+ int sum3 = QtConcurrent::blockingMappedReduced<int>(QLinkedList<int>(list), IntSquare(), IntSumReduce());
+ QCOMPARE(sum3, 14);
+
+ int sum4 = QtConcurrent::blockingMappedReduced<int>(list, intSquare, intSumReduce);
+ QCOMPARE(sum4, 14);
+ int sum5 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(),
+ list.constEnd(),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum5, 14);
+
+ int sum6 = QtConcurrent::blockingMappedReduced<int>(QLinkedList<int>(list),
+ intSquare,
+ intSumReduce);
+ QCOMPARE(sum6, 14);
+ }
+
+ // ### the same as above, with an initial result value
+}
+
+int sleeper(int val)
+{
+ QTest::qSleep(100);
+ return val;
+}
+
+void tst_QtConcurrentMap::assignResult()
+{
+ const QList<int> startList = QList<int>() << 0 << 1 << 2;
+ QList<int> list = QtConcurrent::blockingMapped(startList, sleeper);
+ QCOMPARE(list.at(0), 0);
+ QCOMPARE(list.at(1), 1);
+}
+
+int fnConst(const int &i)
+{
+ return i;
+}
+
+int fn(int &i)
+{
+ return i;
+}
+
+QString changeTypeConst(const int &)
+{
+ return QString();
+}
+
+QString changeType(int &)
+{
+ return QString();
+}
+
+int changeTypeQStringListConst(const QStringList &)
+{
+ return 0;
+}
+
+int changeTypeQStringList(QStringList &)
+{
+ return 0;
+}
+
+class MemFnTester
+{
+public:
+ MemFnTester() {}
+
+ MemFnTester fn()
+ {
+ return MemFnTester();
+ }
+
+ MemFnTester fnConst() const
+ {
+ return MemFnTester();
+ }
+
+ QString changeType()
+ {
+ return QString();
+ }
+
+ QString changeTypeConst() const
+ {
+ return QString();
+ }
+};
+
+Q_DECLARE_METATYPE(QVector<MemFnTester>);
+Q_DECLARE_METATYPE(QList<MemFnTester>);
+
+void tst_QtConcurrentMap::functionOverloads()
+{
+ QList<int> intList;
+ const QList<int> constIntList;
+ QList<MemFnTester> classList;
+ const QList<MemFnTester> constMemFnTesterList;
+
+ QtConcurrent::mapped(intList, fnConst);
+ QtConcurrent::mapped(constIntList, fnConst);
+ QtConcurrent::mapped(classList, &MemFnTester::fnConst);
+ QtConcurrent::mapped(constMemFnTesterList, &MemFnTester::fnConst);
+
+ QtConcurrent::blockingMapped<QVector<int> >(intList, fnConst);
+ QtConcurrent::blockingMapped<QVector<int> >(constIntList, fnConst);
+ QtConcurrent::blockingMapped<QVector<MemFnTester> >(classList, &MemFnTester::fnConst);
+ QtConcurrent::blockingMapped<QVector<MemFnTester> >(constMemFnTesterList, &MemFnTester::fnConst);
+
+ QtConcurrent::blockingMapped<QList<QString> >(intList, changeTypeConst);
+ QtConcurrent::blockingMapped<QList<QString> >(constIntList, changeTypeConst);
+ QtConcurrent::blockingMapped<QList<QString> >(classList, &MemFnTester::changeTypeConst);
+ QtConcurrent::blockingMapped<QList<QString> >(constMemFnTesterList, &MemFnTester::changeTypeConst);
+
+ QStringList stringList;
+ const QStringList constStringList;
+ // QtConcurrent::map(stringList, changeTypeQStringListConst);
+ // QtConcurrent::map(intList, changeTypeNonConst);
+ // QList<QString>(QtConcurrent::map(constStringList, changeTypeQStringList));
+ // QtConcurrent::map(classList, &MemFnTester::changeType);
+ // QtConcurrent::map(classList, &MemFnTester::changeTypeConst);
+ // QtConcurrent::map(constMemFnTesterList, &MemFnTester::changeTypeConst);
+}
+
+QAtomicInt currentInstanceCount;
+QAtomicInt peakInstanceCount;
+class InstanceCounter
+{
+public:
+ inline InstanceCounter()
+ { currentInstanceCount.fetchAndAddRelaxed(1); updatePeak(); }
+ inline ~InstanceCounter()
+ { currentInstanceCount.fetchAndAddRelaxed(-1);}
+ inline InstanceCounter(const InstanceCounter &)
+ { currentInstanceCount.fetchAndAddRelaxed(1); updatePeak(); }
+
+ void updatePeak()
+ {
+ forever {
+ const int localPeak = peakInstanceCount;
+ const int localCurrent = currentInstanceCount;
+ if (localCurrent <= localPeak)
+ break;
+ if (peakInstanceCount.testAndSetOrdered(localPeak, localCurrent))
+ break;
+ }
+ }
+};
+
+InstanceCounter slowMap(const InstanceCounter &in)
+{
+ QTest::qSleep(2);
+ return in;
+}
+
+InstanceCounter fastMap(const InstanceCounter &in)
+{
+ QTest::qSleep(rand() % 2 + 1);
+// qDebug() << "map " << QThread::currentThread();
+ return in;
+}
+
+void slowReduce(int &result, const InstanceCounter&)
+{
+ QTest::qSleep(rand() % 4 + 1);
+// qDebug() << "reduce" << QThread::currentThread();
+ ++result;
+}
+
+void fastReduce(int &result, const InstanceCounter&)
+{
+ ++result;
+}
+
+void tst_QtConcurrentMap::throttling()
+{
+ const int itemcount = 100;
+ const int allowedTemporaries = QThread::idealThreadCount() * 40;
+
+ {
+ currentInstanceCount = 0;
+ peakInstanceCount = 0;
+
+ QList<InstanceCounter> instances;
+ for (int i = 0; i < itemcount; ++i)
+ instances.append(InstanceCounter());
+
+ QCOMPARE((int)currentInstanceCount, itemcount);
+
+ int results = QtConcurrent::blockingMappedReduced(instances, slowMap, fastReduce);
+ QCOMPARE(results, itemcount);
+ qDebug() << (int)currentInstanceCount;
+ qDebug() << (int)peakInstanceCount;
+ QCOMPARE(int(currentInstanceCount), itemcount);
+ QVERIFY(int(peakInstanceCount) < itemcount + allowedTemporaries);
+ }
+
+ {
+ QCOMPARE(int(currentInstanceCount), 0);
+ peakInstanceCount = 0;
+
+ QList<InstanceCounter> instances;
+ for (int i = 0; i < itemcount; ++i)
+ instances.append(InstanceCounter());
+
+ QCOMPARE(int(currentInstanceCount), itemcount);
+ int results = QtConcurrent::blockingMappedReduced(instances, fastMap, slowReduce);
+
+ QCOMPARE(results, itemcount);
+ qDebug() << (int)currentInstanceCount;
+ qDebug() << (int)peakInstanceCount;
+ QCOMPARE((int)currentInstanceCount, itemcount);
+ QVERIFY(int(peakInstanceCount) < itemcount + allowedTemporaries);
+ }
+}
+
+#ifndef QT_NO_EXCEPTIONS
+void throwMapper(int &e)
+{
+ Q_UNUSED(e);
+ throw QtConcurrent::Exception();
+}
+
+void tst_QtConcurrentMap::exceptions()
+{
+ bool caught = false;
+ try {
+ QList<int> list = QList<int>() << 1 << 2 << 3;
+ QtConcurrent::map(list, throwMapper).waitForFinished();
+ } catch (Exception &e) {
+ caught = true;
+ }
+ if (!caught)
+ QFAIL("did not get exception");
+}
+#endif
+
+int mapper(const int &i)
+{
+ QTest::qWait(1);
+ return i;
+}
+
+void tst_QtConcurrentMap::incrementalResults()
+{
+ const int count = 200;
+ QList<int> ints;
+ for (int i=0; i < count; ++i)
+ ints << i;
+
+ QFuture<int> future = QtConcurrent::mapped(ints, mapper);
+
+ QList<int> results;
+
+ while (future.isFinished() == false) {
+ for (int i = 0; i < future.resultCount(); ++i) {
+ results += future.resultAt(i);
+ }
+
+ QTest::qWait(1);
+ }
+
+ QCOMPARE(future.isFinished(), true);
+ QCOMPARE(future.resultCount(), count);
+ QCOMPARE(future.results().count(), count);
+}
+
+/*
+ Test that mapped does not cause deep copies when holding
+ references to Qt containers.
+*/
+void tst_QtConcurrentMap::noDetatch()
+{
+ {
+ QList<int> l = QList<int>() << 1;
+ QVERIFY(l.isDetached());
+
+ QList<int> ll = l;
+ QVERIFY(l.isDetached() == false);
+
+ QtConcurrent::mapped(l, mapper).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+
+ QtConcurrent::mappedReduced(l, mapper, intSumReduce).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+
+ QtConcurrent::map(l, multiplyBy2Immutable).waitForFinished();
+ QVERIFY(l.isDetached() == true);
+ QVERIFY(ll.isDetached() == true);
+ }
+ {
+ const QList<int> l = QList<int>() << 1;
+ QVERIFY(l.isDetached());
+
+ const QList<int> ll = l;
+ QVERIFY(l.isDetached() == false);
+
+ QtConcurrent::mapped(l, mapper).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+
+ QtConcurrent::mappedReduced(l, mapper, intSumReduce).waitForFinished();
+
+ QVERIFY(l.isDetached() == false);
+ QVERIFY(ll.isDetached() == false);
+ }
+
+}
+
+void tst_QtConcurrentMap::stlContainers()
+{
+#ifdef QT_NO_STL
+ QSKIP("Qt compiled without STL support", SkipAll);
+#elif defined(Q_COMPILER_RVALUE_REFS)
+ //mapped uses &Container::push_back, but in c++0x, std::vector has two overload of it
+ // meaning it is not possible to take the address of that function anymore.
+ QSKIP("mapped do not work with c++0x stl vector", SkipAll);
+#else
+ std::vector<int> vector;
+ vector.push_back(1);
+ vector.push_back(2);
+
+ std::vector<int> vector2 = QtConcurrent::blockingMapped<std::vector<int> >(vector, mapper);
+ QCOMPARE(vector2.size(), (std::vector<int>::size_type)(2));
+
+ std::list<int> list;
+ list.push_back(1);
+ list.push_back(2);
+
+ std::list<int> list2 = QtConcurrent::blockingMapped<std::list<int> >(list, mapper);
+ QCOMPARE(list2.size(), (std::vector<int>::size_type)(2));
+
+ QtConcurrent::mapped(list, mapper).waitForFinished();
+
+ QtConcurrent::blockingMap(list, multiplyBy2Immutable);
+#endif
+}
+
+InstanceCounter ic_fn(const InstanceCounter & ic)
+{
+ return InstanceCounter(ic);
+};
+
+// Verify that held results are deleted when a future is
+// assigned over with operator ==
+void tst_QtConcurrentMap::qFutureAssignmentLeak()
+{
+ currentInstanceCount = 0;
+ peakInstanceCount = 0;
+ QFuture<InstanceCounter> future;
+ {
+ QList<InstanceCounter> list;
+ for (int i=0;i<1000;++i)
+ list += InstanceCounter();
+ future = QtConcurrent::mapped(list, ic_fn);
+ future.waitForFinished();
+
+ future = QtConcurrent::mapped(list, ic_fn);
+ future.waitForFinished();
+
+ future = QtConcurrent::mapped(list, ic_fn);
+ future.waitForFinished();
+ }
+
+ QCOMPARE(int(currentInstanceCount), 1000);
+ future = QFuture<InstanceCounter>();
+ QCOMPARE(int(currentInstanceCount), 0);
+}
+
+inline void increment(int &num)
+{
+ ++num;
+}
+
+inline int echo(const int &num)
+{
+ return num;
+}
+
+void add(int &result, const int &sum)
+{
+ result += sum;
+}
+
+void tst_QtConcurrentMap::stressTest()
+{
+ const int listSize = 1000;
+ const int sum = (listSize - 1) * (listSize / 2);
+ QList<int> list;
+
+
+ for (int i = 0; i < listSize; ++i) {
+ list.append(i);
+ }
+
+ for (int i =0 ; i < 100; ++i) {
+ QList<int> result = QtConcurrent::blockingMapped(list, echo);
+ for (int j = 0; j < listSize; ++j)
+ QCOMPARE(result.at(j), j);
+ }
+
+ for (int i = 0 ; i < 100; ++i) {
+ int result = QtConcurrent::blockingMappedReduced(list, echo, add);
+ QCOMPARE(result, sum);
+ }
+
+ for (int i = 0 ; i < 100; ++i) {
+ QtConcurrent::map(list, increment).waitForFinished();
+ for (int j = 0; j < listSize; ++j)
+ QCOMPARE(list.at(j), i + j + 1);
+ }
+}
+
+QTEST_MAIN(tst_QtConcurrentMap)
+
+#else
+
+void tst_QtConcurrentMap::map() {}
+void tst_QtConcurrentMap::blocking_map() {}
+void tst_QtConcurrentMap::mapped() {}
+void tst_QtConcurrentMap::blocking_mapped() {}
+void tst_QtConcurrentMap::mappedReduced() {}
+void tst_QtConcurrentMap::blocking_mappedReduced() {}
+void tst_QtConcurrentMap::assignResult() {}
+void tst_QtConcurrentMap::functionOverloads() {}
+#ifndef QT_NO_EXCEPTIONS
+void tst_QtConcurrentMap::exceptions() {}
+#endif
+void tst_QtConcurrentMap::incrementalResults() {}
+void tst_QtConcurrentMap::stressTest() {}
+void tst_QtConcurrentMap::throttling() {}
+void tst_QtConcurrentMap::stlContainers() {}
+void tst_QtConcurrentMap::noDetatch() {}
+
+QTEST_NOOP_MAIN
+
+#endif
+
+#include "tst_qtconcurrentmap.moc"
diff --git a/tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro b/tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro
new file mode 100644
index 0000000000..8bc20c3f13
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+DEFINES += QT_STRICT_ITERATORS
+SOURCES += tst_qtconcurrentresultstore.cpp
+QT = core core-private
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp b/tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp
new file mode 100644
index 0000000000..1728be68fe
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp
@@ -0,0 +1,491 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qtconcurrentresultstore.h>
+
+using namespace QtConcurrent;
+
+class tst_QtConcurrentResultStore : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+private slots:
+ void construction();
+ void iterators();
+ void addResult();
+ void addResults();
+ void resultIndex();
+ void resultAt();
+ void contains();
+ void filterMode();
+ void addCanceledResult();
+ void count();
+private:
+ int int0;
+ int int1;
+ int int2;
+ QVector<int> vec0;
+ QVector<int> vec1;
+};
+
+void tst_QtConcurrentResultStore::init()
+{
+ int0 = 0;
+ int1 = 1;
+ int2 = 2;
+ vec0 = QVector<int>() << 2 << 3;
+ vec1 = QVector<int>() << 4 << 5;
+}
+
+void tst_QtConcurrentResultStore::construction()
+{
+ ResultStore<int> store;
+ QCOMPARE(store.count(), 0);
+}
+
+void tst_QtConcurrentResultStore::iterators()
+{
+ {
+ ResultStore<int> store;
+ ResultIteratorBase it = store.begin();
+ QVERIFY(store.begin() == store.end());
+ QVERIFY(store.resultAt(0) == store.end());
+ QVERIFY(store.resultAt(1) == store.end());
+ }
+ {
+ ResultStoreBase storebase;
+ storebase.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since
+ storebase.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does.
+ ResultIteratorBase it = storebase.begin();
+ QCOMPARE(it.resultIndex(), 0);
+ QVERIFY(it == storebase.begin());
+ QVERIFY(it != storebase.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 1);
+ QVERIFY(it != storebase.begin());
+ QVERIFY(it != storebase.end());
+
+ ++it;
+ QVERIFY(it != storebase.begin());
+ QVERIFY(it == storebase.end());
+ }
+}
+
+void tst_QtConcurrentResultStore::addResult()
+{
+ {
+ // test addResult return value
+ ResultStore<int> store;
+ store.setFilterMode(true);
+
+ QCOMPARE(store.addResult(0, &int0), 0);
+ QCOMPARE(store.count(), 1); // result 0 becomes available
+ QCOMPARE(store.contains(0), true);
+
+ QCOMPARE(store.addResult(2, &int0), 2);
+ QCOMPARE(store.count(), 1);
+ QCOMPARE(store.contains(2), false);
+
+ QCOMPARE(store.addCanceledResult(1), 1);
+ QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available
+
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), false);
+
+ QCOMPARE(store.addResult(3, &int0), 3);
+ QCOMPARE(store.count(), 3);
+ QCOMPARE(store.contains(2), true);
+
+ QCOMPARE(store.addResult(6, &int0), 6);
+ QCOMPARE(store.count(), 3);
+ QCOMPARE(store.addResult(7, &int0), 7);
+ QCOMPARE(store.count(), 3);
+ QCOMPARE(store.contains(3), false);
+
+ QCOMPARE(store.addCanceledResult(4), 4);
+ QCOMPARE(store.addCanceledResult(5), 5);
+ QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available
+
+ QCOMPARE(store.contains(3), true);
+ QCOMPARE(store.contains(4), true);
+
+ QCOMPARE(store.addResult(8, &int0), 8);
+ QCOMPARE(store.contains(5), true);
+ QCOMPARE(store.count(), 6);
+
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+ }
+}
+
+void tst_QtConcurrentResultStore::addResults()
+{
+
+ ResultStoreBase store;
+ store.addResults(-1, &vec0, 2, 2);
+ store.addResults(-1, &vec1, 2, 2);
+ ResultIteratorBase it = store.begin();
+ QCOMPARE(it.resultIndex(), 0);
+ QVERIFY(it == store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 1);
+ QVERIFY(it != store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 2);
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 3);
+
+ ++it;
+ QVERIFY(it == store.end());
+}
+
+void tst_QtConcurrentResultStore::resultIndex()
+{
+ ResultStore<int> store;
+ store.addResult(-1, &int0);
+ store.addResults(-1, &vec0);
+ store.addResult(-1, &int1);
+
+ ResultIteratorBase it = store.begin();
+ QCOMPARE(it.resultIndex(), 0);
+ QVERIFY(it == store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 1);
+ QVERIFY(it != store.begin());
+ QVERIFY(it != store.end());
+
+ ++it;
+ QCOMPARE(it.resultIndex(), 2);
+ QVERIFY(it != store.end());
+ ++it;
+ QCOMPARE(it.resultIndex(), 3);
+ QVERIFY(it != store.end());
+ ++it;
+ QVERIFY(it == store.end());
+
+ QCOMPARE(store.resultAt(0).value(), int0);
+ QCOMPARE(store.resultAt(1).value(), vec0[0]);
+ QCOMPARE(store.resultAt(2).value(), vec0[1]);
+ QCOMPARE(store.resultAt(3).value(), int1);
+}
+
+void tst_QtConcurrentResultStore::resultAt()
+{
+ {
+ ResultStore<int> store;
+ store.addResult(-1, &int0);
+ store.addResults(-1, &vec0);
+ store.addResult(200, &int1);
+
+ QCOMPARE(store.resultAt(0).value(), int0);
+ QCOMPARE(store.resultAt(1).value(), vec0[0]);
+ QCOMPARE(store.resultAt(2).value(), vec0[1]);
+ QCOMPARE(store.resultAt(200).value(), int1);
+ }
+ {
+ ResultStore<int> store;
+ store.addResult(1, &int1);
+ store.addResult(0, &int0);
+ store.addResult(-1, &int2);
+
+ QCOMPARE(store.resultAt(0).value(), int0);
+ QCOMPARE(store.resultAt(1).value(), int1);
+ QCOMPARE(store.resultAt(2).value(), int2);
+ }
+}
+
+void tst_QtConcurrentResultStore::contains()
+{
+ {
+ ResultStore<int> store;
+ QCOMPARE(store.contains(0), false);
+ QCOMPARE(store.contains(1), false);
+ QCOMPARE(store.contains(INT_MAX), false);
+ store.addResult(1, &int1);
+ QVERIFY(store.contains(int1));
+ store.addResult(0, &int0);
+ QVERIFY(store.contains(int0));
+ store.addResult(-1, &int2);
+ QVERIFY(store.contains(int2));
+ }
+ {
+ ResultStore<int> store;
+ store.addResult(1, &int0);
+ store.addResult(3, &int0);
+ store.addResults(6, &vec0);
+ QCOMPARE(store.contains(0), false);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), false);
+ QCOMPARE(store.contains(3), true);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(6), true);
+ QCOMPARE(store.contains(7), true);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResult(1, &int0);
+ store.addResult(3, &int0);
+ store.addResults(6, &vec0);
+ QCOMPARE(store.contains(0), false);
+ QCOMPARE(store.contains(1), false);
+ QCOMPARE(store.contains(2), false);
+ QCOMPARE(store.contains(3), false);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+
+ store.addCanceledResult(0);
+ store.addCanceledResult(2);
+ store.addCanceledResults(4, 2);
+
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), true);
+ QCOMPARE(store.contains(3), true);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+ }
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addCanceledResult(0);
+ QCOMPARE(store.contains(0), false);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), false);
+ }
+}
+
+void tst_QtConcurrentResultStore::filterMode()
+{
+ // Test filter mode, where "gaps" in the result array aren't allowed.
+ ResultStore<int> store;
+ QCOMPARE(store.filterMode(), false);
+ store.setFilterMode(true);
+ QVERIFY(store.filterMode());
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.contains(0), true);
+
+ store.addResult(2, &int2); // add result at index 2
+ QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet.
+
+ store.addResult(1, &int1);
+ QCOMPARE(store.contains(1), true);
+ QCOMPARE(store.contains(2), true); // 2 should be visible now.
+
+ store.addResult(4, &int0);
+ store.addResult(5, &int0);
+ store.addResult(7, &int0);
+ QCOMPARE(store.contains(4), false);
+ QCOMPARE(store.contains(5), false);
+ QCOMPARE(store.contains(7), false);
+
+ store.addResult(3, &int0); // adding 3 makes 4 and 5 visible
+ QCOMPARE(store.contains(4), true);
+ QCOMPARE(store.contains(5), true);
+ QCOMPARE(store.contains(7), false);
+
+ store.addResult(6, &int0); // adding 6 makes 7 visible
+
+ QCOMPARE(store.contains(6), true);
+ QCOMPARE(store.contains(7), true);
+ QCOMPARE(store.contains(8), false);
+}
+
+void tst_QtConcurrentResultStore::addCanceledResult()
+{
+ // test canceled results
+ ResultStore<int> store;
+ store.setFilterMode(true);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.contains(0), true);
+
+ store.addResult(2, &int0);
+ QCOMPARE(store.contains(2), false);
+
+ store.addCanceledResult(1); // report no result at 1
+
+ QCOMPARE(store.contains(0), true);
+ QCOMPARE(store.contains(1), true); // 2 gets renamed to 1
+ QCOMPARE(store.contains(2), false);
+
+ store.addResult(3, &int0);
+ QCOMPARE(store.contains(2), true); //3 gets renamed to 2
+
+ store.addResult(6, &int0);
+ store.addResult(7, &int0);
+ QCOMPARE(store.contains(3), false);
+
+ store.addCanceledResult(4);
+ store.addCanceledResult(5);
+
+ QCOMPARE(store.contains(3), true); //6 gets renamed to 3
+ QCOMPARE(store.contains(4), true); //7 gets renamed to 4
+
+ store.addResult(8, &int0);
+ QCOMPARE(store.contains(5), true); //8 gets renamed to 4
+
+ QCOMPARE(store.contains(6), false);
+ QCOMPARE(store.contains(7), false);
+}
+
+void tst_QtConcurrentResultStore::count()
+{
+ {
+ // test resultCount in non-filtered mode. It should always be possible
+ // to iterate through the results 0 to resultCount.
+ ResultStore<int> store;
+ store.addResult(0, &int0);
+
+ QCOMPARE(store.count(), 1);
+
+ store.addResult(2, &int0);
+
+ QCOMPARE(store.count(), 1);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.count(), 3);
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResult(2, &int0);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.count(), 3);
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResults(2, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(1, &int0);
+ QCOMPARE(store.count(), 0);
+
+ store.addResult(0, &int0);
+ QCOMPARE(store.count(), 4);
+ }
+
+ {
+ ResultStore<int> store;
+ store.addResults(2, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResults(0, &vec0);
+ QCOMPARE(store.count(), 4);
+ }
+ {
+ ResultStore<int> store;
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResults(0, &vec0);
+ QCOMPARE(store.count(), 2);
+
+ store.addResult(2, &int0);
+ QCOMPARE(store.count(), 5);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addResults(0, &vec0);
+ QCOMPARE(store.count(), 2);
+
+ store.addCanceledResult(2);
+ QCOMPARE(store.count(), 4);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addCanceledResults(0, 3);
+ QCOMPARE(store.count(), 2);
+ }
+
+ {
+ ResultStore<int> store;
+ store.setFilterMode(true);
+ store.addResults(3, &vec1);
+ QCOMPARE(store.count(), 0);
+
+ store.addCanceledResults(0, 3);
+ QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1
+
+ store.addResult(5, &int0);
+ QCOMPARE(store.count(), 3);// result 5 becomes available at index 2
+ }
+}
+
+QTEST_MAIN(tst_QtConcurrentResultStore)
+#include "tst_qtconcurrentresultstore.moc"
diff --git a/tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore
new file mode 100644
index 0000000000..d7a8334ec4
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore
@@ -0,0 +1 @@
+tst_qtconcurrentrun
diff --git a/tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro b/tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro
new file mode 100644
index 0000000000..24576048e9
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qtconcurrentrun.cpp
+QT = core
+CONFIG += parallel_test
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
new file mode 100644
index 0000000000..cacb09aae1
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
@@ -0,0 +1,518 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtconcurrentrun.h>
+// #include <qtconcurrentcreatefunctor.h>
+#include <qfuture.h>
+#include <QString>
+#include <QtTest/QtTest>
+#include "../qfuture/versioncheck.h"
+
+#ifndef QT_NO_CONCURRENT_TEST
+
+using namespace QtConcurrent;
+
+class tst_QtConcurrentRun: public QObject
+{
+ Q_OBJECT
+private slots:
+ void runLightFunction();
+ void runHeavyFunction();
+ void returnValue();
+ void functionObject();
+ void memberFunctions();
+ void implicitConvertibleTypes();
+ void runWaitLoop();
+ void recursive();
+#ifndef QT_NO_EXCEPTIONS
+ void exceptions();
+#endif
+#if 0
+ void createFunctor();
+#endif
+ void functor();
+ void lambda();
+};
+
+#if 0
+# define F(X) createFunctor(X)
+#else
+# define F(X) X
+#endif
+
+
+QTEST_MAIN(tst_QtConcurrentRun)
+
+void light()
+{
+ qDebug("in function");
+ qDebug("done function");
+}
+
+void heavy()
+{
+ qDebug("in function");
+ QString str;
+ for (int i = 0; i < 1000000; ++i)
+ str.append("a");
+ qDebug("done function");
+}
+
+
+void tst_QtConcurrentRun::runLightFunction()
+{
+ qDebug("starting function");
+ QFuture<void> future = run(F(light));
+ qDebug("waiting");
+ future.waitForFinished();
+ qDebug("done");
+}
+
+void tst_QtConcurrentRun::runHeavyFunction()
+{
+ qDebug("starting function");
+ QFuture<void> future = run(F(heavy));
+ qDebug("waiting");
+ future.waitForFinished();
+ qDebug("done");
+}
+
+int returnInt0()
+{
+ return 10;
+}
+
+int returnInt1(int i)
+{
+ return i;
+}
+
+class A
+{
+public:
+ int member0() { return 10; }
+ int member1(int in) { return in; }
+
+ typedef int result_type;
+ int operator()() { return 10; }
+ int operator()(int in) { return in; }
+};
+
+class AConst
+{
+public:
+ int member0() const { return 10; }
+ int member1(int in) const { return in; }
+
+ typedef int result_type;
+ int operator()() const { return 10; }
+ int operator()(int in) const { return in; }
+};
+
+void tst_QtConcurrentRun::returnValue()
+{
+ QFuture<int> f;
+
+ f = run(F(returnInt0));
+ QCOMPARE(f.result(), 10);
+
+ A a;
+ f = run(&a, F(&A::member0));
+ QCOMPARE(f.result(), 10);
+
+ f = run(&a, F(&A::member1), 20);
+ QCOMPARE(f.result(), 20);
+
+ f = run(a, F(&A::member0));
+ QCOMPARE(f.result(), 10);
+
+ f = run(a, F(&A::member1), 20);
+ QCOMPARE(f.result(), 20);
+
+ f = run(a);
+ QCOMPARE(f.result(), 10);
+
+ f = run(&a);
+ QCOMPARE(f.result(), 10);
+
+ f = run(a, 20);
+ QCOMPARE(f.result(), 20);
+
+ f = run(&a, 20);
+ QCOMPARE(f.result(), 20);
+
+ const AConst aConst = AConst();
+ f = run(&aConst, &AConst::member0);
+ QCOMPARE(f.result(), 10);
+
+ f = run(&aConst, F(&AConst::member1), 20);
+ QCOMPARE(f.result(), 20);
+
+ f = run(aConst, F(&AConst::member0));
+ QCOMPARE(f.result(), 10);
+
+ f = run(aConst, F(&AConst::member1), 20);
+ QCOMPARE(f.result(), 20);
+
+ f = run(aConst);
+ QCOMPARE(f.result(), 10);
+
+ f = run(&aConst);
+ QCOMPARE(f.result(), 10);
+
+ f = run(aConst, 20);
+ QCOMPARE(f.result(), 20);
+
+ f = run(&aConst, 20);
+ QCOMPARE(f.result(), 20);
+}
+
+struct TestClass
+{
+ void foo() { }
+ typedef void result_type;
+ void operator()() { }
+ void operator()(int) { }
+ void fooInt(int){ };
+};
+
+struct TestConstClass
+{
+ void foo() const { }
+ typedef void result_type;
+ void operator()() const { }
+ void operator()(int) const { }
+ void fooInt(int) const { };
+};
+
+void tst_QtConcurrentRun::functionObject()
+{
+ QFuture<void> f;
+ TestClass c;
+
+ f = run(c);
+ f = run(F(&c));
+ f = run(c, 10);
+ f = run(F(&c), 10);
+
+ const TestConstClass cc = TestConstClass();
+ f = run(cc);
+ f = run(F(&cc));
+ f = run(cc, 10);
+ f = run(F(&cc), 10);
+}
+
+
+void tst_QtConcurrentRun::memberFunctions()
+{
+ TestClass c;
+
+ run(c, F(&TestClass::foo)).waitForFinished();
+ run(&c, F(&TestClass::foo)).waitForFinished();
+ run(c, F(&TestClass::fooInt), 10).waitForFinished();
+ run(&c, F(&TestClass::fooInt), 10).waitForFinished();
+
+ const TestConstClass cc = TestConstClass();
+ run(cc, F(&TestConstClass::foo)).waitForFinished();
+ run(&cc, F(&TestConstClass::foo)).waitForFinished();
+ run(cc, F(&TestConstClass::fooInt), 10).waitForFinished();
+ run(&cc, F(&TestConstClass::fooInt), 10).waitForFinished();
+}
+
+
+void doubleFunction(double)
+{
+
+}
+
+void stringConstRefFunction(const QString &)
+{
+
+}
+
+void stringRefFunction(QString &)
+{
+
+}
+
+void stringFunction(QString)
+{
+
+}
+
+void stringIntFunction(QString)
+{
+
+}
+
+
+void tst_QtConcurrentRun::implicitConvertibleTypes()
+{
+ double d;
+ run(F(doubleFunction), d).waitForFinished();
+ int i;
+ run(F(doubleFunction), d).waitForFinished();
+ run(F(doubleFunction), i).waitForFinished();
+ run(F(doubleFunction), 10).waitForFinished();
+ run(F(stringFunction), QLatin1String("Foo")).waitForFinished();
+ run(F(stringConstRefFunction), QLatin1String("Foo")).waitForFinished();
+ QString string;
+ run(F(stringRefFunction), string).waitForFinished();
+}
+
+void fn() { }
+
+void tst_QtConcurrentRun::runWaitLoop()
+{
+ for (int i = 0; i < 1000; ++i)
+ run(fn).waitForFinished();
+}
+
+QAtomicInt count;
+
+void recursiveRun(int level)
+{
+ count.ref();
+ if (--level > 0) {
+ QFuture<void> f1 = run(recursiveRun, level);
+ QFuture<void> f2 = run(recursiveRun, level);
+ f1.waitForFinished();
+ f2.waitForFinished();
+ }
+}
+
+int recursiveResult(int level)
+{
+ count.ref();
+ if (--level > 0) {
+ QFuture<int> f1 = run(recursiveResult, level);
+ QFuture<int> f2 = run(recursiveResult, level);
+ return f1.result() + f2.result();
+ }
+ return 1;
+}
+
+void tst_QtConcurrentRun::recursive()
+{
+ int levels = 15;
+
+ for (int i = 0; i < QThread::idealThreadCount(); ++i) {
+ count = 0;
+ QThreadPool::globalInstance()->setMaxThreadCount(i);
+ recursiveRun(levels);
+ QCOMPARE((int)count, (int)pow(2.0, levels) - 1);
+ }
+
+ for (int i = 0; i < QThread::idealThreadCount(); ++i) {
+ count = 0;
+ QThreadPool::globalInstance()->setMaxThreadCount(i);
+ recursiveResult(levels);
+ QCOMPARE((int)count, (int)pow(2.0, levels) - 1);
+ }
+}
+
+int e;
+void vfn0()
+{
+ ++e;
+}
+
+int fn0()
+{
+ return 1;
+}
+
+void vfn1(double)
+{
+ ++e;
+}
+
+int fn1(int)
+{
+ return 1;
+}
+
+void vfn2(double, int *)
+{
+ ++e;
+}
+
+int fn2(double, int *)
+{
+ return 1;
+}
+
+
+#ifndef QT_NO_EXCEPTIONS
+void throwFunction()
+{
+ throw QtConcurrent::Exception();
+}
+
+int throwFunctionReturn()
+{
+ throw QtConcurrent::Exception();
+ return 0;
+}
+
+void tst_QtConcurrentRun::exceptions()
+{
+ bool caught = false;
+ try {
+ QtConcurrent::run(throwFunction).waitForFinished();
+ } catch (Exception &e) {
+ caught = true;
+ }
+ if (!caught)
+ QFAIL("did not get exception");
+
+ caught = false;
+ try {
+ QtConcurrent::run(throwFunctionReturn).waitForFinished();
+ } catch (Exception &e) {
+ caught = true;
+ }
+ if (!caught)
+ QFAIL("did not get exception");
+}
+#endif
+
+#if 0
+void tst_QtConcurrentRun::createFunctor()
+{
+ e = 0;
+ ::QtConcurrent::createFunctor(vfn0)();
+ e += QtConcurrent::createFunctor(fn0)();
+ ::QtConcurrent::createFunctor(vfn1)(1); // implicit conversions should work
+ e += QtConcurrent::createFunctor(fn1)(2);
+ ::QtConcurrent::createFunctor(vfn2)(1.0, &e);
+ e += QtConcurrent::createFunctor(fn2)(2, &e);
+ QCOMPARE(e, 6);
+
+
+ e = 0;
+ TestClass c;
+
+// ::QtConcurrent::createFunctor(c, &TestClass::foo)();
+ ::QtConcurrent::createFunctor(&c, &TestClass::foo)();
+// ::QtConcurrent::createFunctor(c, &TestClass::fooInt)(10);
+ ::QtConcurrent::createFunctor(&c, &TestClass::fooInt)(10);
+
+ const TestConstClass cc = TestConstClass();
+/*
+ ::QtConcurrent::createFunctor(cc, &TestConstClass::foo)();
+ ::QtConcurrent::createFunctor(&cc, &TestConstClass::foo)();
+ ::QtConcurrent::createFunctor(cc, &TestConstClass::fooInt(10);
+ ::QtConcurrent::createFunctor(&cc, &TestConstClass::fooInt)(10);
+*/
+ qDebug() << e;
+}
+#endif
+
+struct Functor {
+ int operator()() { return 42; }
+ double operator()(double a, double b) { return a/b; }
+ int operator()(int a, int b) { return a/b; }
+ void operator()(int) { }
+ void operator()(int, int, int) { }
+ void operator()(int, int, int, int) { }
+ void operator()(int, int, int, int, int) { }
+ void operator()(int, int, int, int, int, int) { }
+};
+
+void tst_QtConcurrentRun::functor()
+{
+ //this test functor without result_type, decltype need to be supported by the compiler
+#ifndef Q_COMPILER_DECLTYPE
+ QSKIP("Compiler do not suport decltype", SkipAll);
+#else
+ Functor f;
+ {
+ QFuture<int> fut = QtConcurrent::run(f);
+ QCOMPARE(fut.result(), 42);
+ }
+ {
+ QFuture<double> fut = QtConcurrent::run(f, 8.5, 1.8);
+ QCOMPARE(fut.result(), (8.5/1.8));
+ }
+ {
+ QFuture<int> fut = QtConcurrent::run(f, 19, 3);
+ QCOMPARE(fut.result(), int(19/3));
+ }
+ {
+ QtConcurrent::run(f, 1).waitForFinished();
+ QtConcurrent::run(f, 1,2).waitForFinished();
+ QtConcurrent::run(f, 1,2,3).waitForFinished();
+ QtConcurrent::run(f, 1,2,3,4).waitForFinished();
+ QtConcurrent::run(f, 1,2,3,4,5).waitForFinished();
+ }
+#endif
+}
+
+
+void tst_QtConcurrentRun::lambda()
+{
+#ifndef Q_COMPILER_LAMBDA
+ QSKIP("Compiler do not suport lambda", SkipAll);
+#else
+
+ QCOMPARE(QtConcurrent::run([](){ return 45; }).result(), 45);
+ QCOMPARE(QtConcurrent::run([](int a){ return a+15; }, 12).result(), 12+15);
+ QCOMPARE(QtConcurrent::run([](int a, double b){ return a + b; }, 12, 15).result(), double(12+15));
+ QCOMPARE(QtConcurrent::run([](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5);
+
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+ {
+ QString str { "Hello World Foo" };
+ QFuture<QStringList> f1 = QtConcurrent::run([&](){ return str.split(' '); });
+ auto r = f1.result();
+ QCOMPARE(r, QStringList({"Hello", "World", "Foo"}));
+ }
+#endif
+
+#endif
+}
+
+
+#include "tst_qtconcurrentrun.moc"
+
+#else
+QTEST_NOOP_MAIN
+#endif
diff --git a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore
new file mode 100644
index 0000000000..a2e2896246
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore
@@ -0,0 +1 @@
+tst_qtconcurrentthreadengine
diff --git a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro
new file mode 100644
index 0000000000..bbfcf5ebe3
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_qtconcurrentthreadengine.cpp
+QT = core
+CONFIG += parallel_test
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
new file mode 100644
index 0000000000..772c749711
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
@@ -0,0 +1,536 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtconcurrentthreadengine.h>
+#include <qtconcurrentexception.h>
+#include <QThread>
+#include <QtTest/QtTest>
+#include "../qfuture/versioncheck.h"
+
+#ifndef QT_NO_CONCURRENT_TEST
+
+using namespace QtConcurrent;
+
+class tst_QtConcurrentThreadEngine: public QObject
+{
+ Q_OBJECT
+public:
+ void threadCount();
+private slots:
+ void runDirectly();
+ void result();
+ void runThroughStarter();
+ void cancel();
+ void throttle();
+ void multipleResults();
+ void stresstest();
+ void cancelQueuedSlowUser();
+#ifndef QT_NO_EXCEPTIONS
+ void exceptions();
+#endif
+};
+
+
+class PrintUser : public ThreadEngine<void>
+{
+public:
+ ThreadFunctionResult threadFunction()
+ {
+ QTest::qSleep(50);
+ QTest::qSleep(100);
+ return ThreadFinished;
+ }
+};
+
+void tst_QtConcurrentThreadEngine::runDirectly()
+{
+ {
+ PrintUser engine;
+ engine.startSingleThreaded();
+ engine.startBlocking();
+ }
+ {
+ PrintUser *engine = new PrintUser();
+ QFuture<void> f = engine->startAsynchronously();
+ f.waitForFinished();
+ }
+}
+
+class StringResultUser : public ThreadEngine<QString>
+{
+public:
+ typedef QString ResultType;
+ StringResultUser()
+ : done(false) { }
+
+ bool shouldStartThread()
+ {
+ return !done;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ done = true;
+ return ThreadFinished;
+ }
+
+ QString *result()
+ {
+ foo = "Foo";
+ return &foo;
+ }
+ QString foo;
+ bool done;
+};
+
+void tst_QtConcurrentThreadEngine::result()
+{
+ StringResultUser engine;
+ QCOMPARE(*engine.startBlocking(), QString("Foo"));
+}
+
+class VoidResultUser : public ThreadEngine<void>
+{
+public:
+ bool shouldStartThread()
+ {
+ return !done;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ done = true;
+ return ThreadFinished;
+ }
+
+ void *result()
+ {
+ return 0;
+ }
+ bool done;
+};
+
+void tst_QtConcurrentThreadEngine::runThroughStarter()
+{
+ {
+ ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
+ QFuture<QString> f = starter.startAsynchronously();
+ QCOMPARE(f.result(), QString("Foo"));
+ }
+
+ {
+ ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
+ QString str = starter.startBlocking();
+ QCOMPARE(str, QString("Foo"));
+ }
+}
+
+class CancelUser : public ThreadEngine<void>
+{
+public:
+ void *result()
+ {
+ return 0;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ while (this->isCanceled() == false)
+ {
+ QTest::qSleep(10);
+ }
+ return ThreadFinished;
+ }
+};
+
+void tst_QtConcurrentThreadEngine::cancel()
+{
+ {
+ CancelUser *engine = new CancelUser();
+ QFuture<void> f = engine->startAsynchronously();
+ f.cancel();
+ f.waitForFinished();
+ }
+ {
+ CancelUser *engine = new CancelUser();
+ QFuture<void> f = engine->startAsynchronously();
+ QTest::qSleep(10);
+ f.cancel();
+ f.waitForFinished();
+ }
+}
+
+QAtomicInt count;
+class ThrottleAlwaysUser : public ThreadEngine<void>
+{
+public:
+ ThrottleAlwaysUser()
+ {
+ count = initialCount = 100;
+ finishing = false;
+ }
+
+ bool shouldStartThread()
+ {
+ return !finishing;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ forever {
+ const int local = count;
+ if (local == 0) {
+ finishing = true;
+ return ThreadFinished;
+ }
+
+ if (count.testAndSetOrdered(local, local - 1))
+ break;
+ }
+ return ThrottleThread;
+ }
+
+ bool finishing;
+ int initialCount;
+};
+
+// Test that a user task with a thread function that always
+// want to be throttled still completes. The thread engine
+// should make keep one thread running at all times.
+void tst_QtConcurrentThreadEngine::throttle()
+{
+ const int repeats = 10;
+ for (int i = 0; i < repeats; ++i) {
+ QFuture<void> f = (new ThrottleAlwaysUser())->startAsynchronously();
+ f.waitForFinished();
+ QCOMPARE(int(count), 0);
+ }
+
+ for (int i = 0; i < repeats; ++i) {
+ ThrottleAlwaysUser t;
+ t.startBlocking();
+ QCOMPARE(int(count), 0);
+ }
+}
+
+QSet<QThread *> threads;
+QMutex mutex;
+class ThreadCountUser : public ThreadEngine<void>
+{
+public:
+ ThreadCountUser(bool finishImmediately = false)
+ {
+ threads.clear();
+ finishing = finishImmediately;
+ }
+
+ bool shouldStartThread()
+ {
+ return !finishing;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ {
+ QMutexLocker lock(&mutex);
+ threads.insert(QThread::currentThread());
+ }
+ QTest::qSleep(10);
+ finishing = true;
+ return ThreadFinished;
+ }
+
+ bool finishing;
+};
+
+void tst_QtConcurrentThreadEngine::threadCount()
+{
+ const int repeats = 10;
+ for (int i = 0; i < repeats; ++i) {
+ ThreadCountUser t;
+ t.startBlocking();
+ QCOMPARE(threads.count(), QThreadPool::globalInstance()->maxThreadCount() + 1); // +1 for the main thread.
+
+ (new ThreadCountUser())->startAsynchronously().waitForFinished();
+ QCOMPARE(threads.count(), QThreadPool::globalInstance()->maxThreadCount());
+ }
+
+ // Set the finish flag immediately, this should give us one thread only.
+ for (int i = 0; i < repeats; ++i) {
+ ThreadCountUser t(true /*finishImmediately*/);
+ t.startBlocking();
+ QCOMPARE(threads.count(), 1);
+
+ (new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished();
+ QCOMPARE(threads.count(), 1);
+ }
+}
+
+class MultipleResultsUser : public ThreadEngine<int>
+{
+public:
+ bool shouldStartThread()
+ {
+ return false;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ for (int i = 0; i < 10; ++i)
+ this->reportResult(&i);
+ return ThreadFinished;
+ }
+};
+
+
+void tst_QtConcurrentThreadEngine::multipleResults()
+{
+ MultipleResultsUser *engine = new MultipleResultsUser();
+ QFuture<int> f = engine->startAsynchronously();
+ QCOMPARE(f.results().count() , 10);
+ QCOMPARE(f.resultAt(0), 0);
+ QCOMPARE(f.resultAt(5), 5);
+ QCOMPARE(f.resultAt(9), 9);
+ f.waitForFinished();
+}
+
+
+class NoThreadsUser : public ThreadEngine<void>
+{
+public:
+ bool shouldStartThread()
+ {
+ return false;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ return ThreadFinished;
+ }
+
+ void *result()
+ {
+ return 0;
+ }
+};
+
+void tst_QtConcurrentThreadEngine::stresstest()
+{
+ const int times = 20000;
+
+ for (int i = 0; i < times; ++i) {
+ VoidResultUser *engine = new VoidResultUser();
+ engine->startAsynchronously().waitForFinished();
+ }
+
+ for (int i = 0; i < times; ++i) {
+ VoidResultUser *engine = new VoidResultUser();
+ engine->startAsynchronously();
+ }
+
+ for (int i = 0; i < times; ++i) {
+ VoidResultUser *engine = new VoidResultUser();
+ engine->startAsynchronously().waitForFinished();
+ }
+}
+
+const int sleepTime = 20;
+class SlowUser : public ThreadEngine<void>
+{
+public:
+ bool shouldStartThread() { return false; }
+ ThreadFunctionResult threadFunction() { QTest::qSleep(sleepTime); return ThreadFinished; }
+};
+
+void tst_QtConcurrentThreadEngine::cancelQueuedSlowUser()
+{
+ const int times = 100;
+
+ QTime t;
+ t.start();
+
+ {
+ QList<QFuture<void> > futures;
+ for (int i = 0; i < times; ++i) {
+ SlowUser *engine = new SlowUser();
+ futures.append(engine->startAsynchronously());
+ }
+
+ foreach(QFuture<void> future, futures)
+ future.cancel();
+ }
+
+ QVERIFY(t.elapsed() < (sleepTime * times) / 2);
+}
+
+#ifndef QT_NO_EXCEPTIONS
+
+class QtConcurrentExceptionThrower : public ThreadEngine<void>
+{
+public:
+ QtConcurrentExceptionThrower(QThread *blockThread = 0)
+ {
+ this->blockThread = blockThread;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ QTest::qSleep(50);
+ throw QtConcurrent::Exception();
+ return ThreadFinished;
+ }
+ QThread *blockThread;
+};
+
+class UnrelatedExceptionThrower : public ThreadEngine<void>
+{
+public:
+ UnrelatedExceptionThrower(QThread *blockThread = 0)
+ {
+ this->blockThread = blockThread;
+ }
+
+ ThreadFunctionResult threadFunction()
+ {
+ QTest::qSleep(50);
+ throw int();
+ return ThreadFinished;
+ }
+ QThread *blockThread;
+};
+
+void tst_QtConcurrentThreadEngine::exceptions()
+{
+ // Asynchronous mode:
+ {
+ bool caught = false;
+ try {
+ QtConcurrentExceptionThrower *e = new QtConcurrentExceptionThrower();
+ QFuture<void> f = e->startAsynchronously();
+ f.waitForFinished();
+ } catch (Exception &e) {
+ caught = true;
+ }
+ if (!caught)
+ QFAIL("did not get exception");
+ }
+
+ // Blocking mode:
+ // test throwing the exception from a worker thread.
+ {
+ bool caught = false;
+ try {
+ QtConcurrentExceptionThrower e(QThread::currentThread());
+ e.startBlocking();
+ } catch (Exception &e) {
+ caught = true;
+ }
+
+ if (!caught)
+ QFAIL("did not get exception");
+ }
+
+ // test throwing the exception from the main thread (different code path)
+ {
+ bool caught = false;
+ try {
+ QtConcurrentExceptionThrower e(0);
+ e.startBlocking();
+ } catch (Exception &e) {
+ caught = true;
+ }
+
+ if (!caught)
+ QFAIL("did not get exception");
+ }
+
+ // Asynchronous mode:
+ {
+ bool caught = false;
+ try {
+ UnrelatedExceptionThrower *e = new UnrelatedExceptionThrower();
+ QFuture<void> f = e->startAsynchronously();
+ f.waitForFinished();
+ } catch (QtConcurrent::UnhandledException &e) {
+ caught = true;
+ }
+ if (!caught)
+ QFAIL("did not get exception");
+ }
+
+ // Blocking mode:
+ // test throwing the exception from a worker thread.
+ {
+ bool caught = false;
+ try {
+ UnrelatedExceptionThrower e(QThread::currentThread());
+ e.startBlocking();
+ } catch (QtConcurrent::UnhandledException &e) {
+ caught = true;
+ }
+
+ if (!caught)
+ QFAIL("did not get exception");
+ }
+
+ // test throwing the exception from the main thread (different code path)
+ {
+ bool caught = false;
+ try {
+ UnrelatedExceptionThrower e(0);
+ e.startBlocking();
+ } catch (QtConcurrent::UnhandledException &e) {
+ caught = true;
+ }
+
+ if (!caught)
+ QFAIL("did not get exception");
+ }
+}
+
+#endif
+
+QTEST_MAIN(tst_QtConcurrentThreadEngine)
+
+#include "tst_qtconcurrentthreadengine.moc"
+
+#else
+QTEST_NOOP_MAIN
+#endif
diff --git a/tests/auto/corelib/concurrent/qthreadpool/.gitignore b/tests/auto/corelib/concurrent/qthreadpool/.gitignore
new file mode 100644
index 0000000000..16105821a2
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qthreadpool/.gitignore
@@ -0,0 +1 @@
+tst_qthreadpool
diff --git a/tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro b/tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro
new file mode 100644
index 0000000000..dbaeb208dd
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+SOURCES += tst_qthreadpool.cpp
+QT = core
+CONFIG += parallel_test
diff --git a/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp
new file mode 100644
index 0000000000..49c517a569
--- /dev/null
+++ b/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp
@@ -0,0 +1,870 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <qdatetime.h>
+#include <qthreadpool.h>
+#include <qstring.h>
+#include <qmutex.h>
+
+typedef void (*FunctionPointer)();
+
+class FunctionPointerTask : public QRunnable
+{
+public:
+ FunctionPointerTask(FunctionPointer function)
+ :function(function) {}
+ void run() { function(); }
+private:
+ FunctionPointer function;
+};
+
+QRunnable *createTask(FunctionPointer pointer)
+{
+ return new FunctionPointerTask(pointer);
+}
+
+class tst_QThreadPool : public QObject
+{
+ Q_OBJECT
+private slots:
+ void runFunction();
+ void createThreadRunFunction();
+ void runMultiple();
+ void waitcomplete();
+ void runTask();
+ void singleton();
+ void destruction();
+ void threadRecycling();
+ void expiryTimeout();
+ void exceptions();
+ void maxThreadCount();
+ void setMaxThreadCount_data();
+ void setMaxThreadCount();
+ void setMaxThreadCountStartsAndStopsThreads();
+ void activeThreadCount();
+ void reserveThread_data();
+ void reserveThread();
+ void releaseThread_data();
+ void releaseThread();
+ void start();
+ void tryStart();
+ void tryStartPeakThreadCount();
+ void tryStartCount();
+ void waitForDone();
+ void waitForDoneTimeout();
+ void destroyingWaitsForTasksToFinish();
+ void stressTest();
+};
+
+int testFunctionCount;
+
+void sleepTestFunction()
+{
+ QTest::qSleep(1000);
+ ++testFunctionCount;
+}
+
+void emptyFunct()
+{
+
+}
+
+void noSleepTestFunction()
+{
+ ++testFunctionCount;
+}
+
+void sleepTestFunctionMutex()
+{
+ static QMutex testMutex;
+ QTest::qSleep(1000);
+ testMutex.lock();
+ ++testFunctionCount;
+ testMutex.unlock();
+}
+
+void noSleepTestFunctionMutex()
+{
+ static QMutex testMutex;
+ testMutex.lock();
+ ++testFunctionCount;
+ testMutex.unlock();
+}
+
+void tst_QThreadPool::runFunction()
+{
+ {
+ QThreadPool manager;
+ testFunctionCount = 0;
+ manager.start(createTask(noSleepTestFunction));
+ }
+ QCOMPARE(testFunctionCount, 1);
+}
+
+void tst_QThreadPool::createThreadRunFunction()
+{
+ {
+ QThreadPool manager;
+ testFunctionCount = 0;
+ manager.start(createTask(noSleepTestFunction));
+ }
+
+ QCOMPARE(testFunctionCount, 1);
+}
+
+void tst_QThreadPool::runMultiple()
+{
+ const int runs = 10;
+
+ {
+ QThreadPool manager;
+ testFunctionCount = 0;
+ for (int i = 0; i < runs; ++i) {
+ manager.start(createTask(sleepTestFunctionMutex));
+ }
+ }
+ QCOMPARE(testFunctionCount, runs);
+
+ {
+ QThreadPool manager;
+ testFunctionCount = 0;
+ for (int i = 0; i < runs; ++i) {
+ manager.start(createTask(noSleepTestFunctionMutex));
+ }
+ }
+ QCOMPARE(testFunctionCount, runs);
+
+ {
+ QThreadPool manager;
+ for (int i = 0; i < 500; ++i)
+ manager.start(createTask(emptyFunct));
+ }
+}
+
+void tst_QThreadPool::waitcomplete()
+{
+ testFunctionCount = 0;
+ const int runs = 500;
+ for (int i = 0; i < 500; ++i) {
+ QThreadPool pool;
+ pool.start(createTask(noSleepTestFunction));
+ }
+ QCOMPARE(testFunctionCount, runs);
+}
+
+volatile bool ran;
+class TestTask : public QRunnable
+{
+public:
+ void run()
+ {
+ ran = true;
+ }
+};
+
+void tst_QThreadPool::runTask()
+{
+ QThreadPool manager;
+ ran = false;
+ manager.start(new TestTask());
+ // Hang if task is not runned.
+ while (ran == false)
+ QTest::qSleep(100); // no busy loop - this doesn't work with FIFO schedulers
+}
+
+/*
+ Test running via QThreadPool::globalInstance()
+*/
+void tst_QThreadPool::singleton()
+{
+ ran = false;
+ QThreadPool::globalInstance()->start(new TestTask());
+ while (ran == false)
+ QTest::qSleep(100); // no busy loop - this doesn't work with FIFO schedulers
+}
+
+int *value = 0;
+class IntAccessor : public QRunnable
+{
+public:
+ void run()
+ {
+ for (int i = 0; i < 100; ++i) {
+ ++(*value);
+ QTest::qSleep(1);
+ }
+ }
+};
+
+/*
+ Test that the ThreadManager destructor waits until
+ all threads have completed.
+*/
+void tst_QThreadPool::destruction()
+{
+ value = new int;
+ QThreadPool *threadManager = new QThreadPool();
+ threadManager->start(new IntAccessor());
+ threadManager->start(new IntAccessor());
+ delete threadManager;
+ delete value;
+ value = 0;
+}
+
+QSemaphore threadRecyclingSemaphore;
+QThread *recycledThread = 0;
+
+class ThreadRecorderTask : public QRunnable
+{
+public:
+ void run()
+ {
+ recycledThread = QThread::currentThread();
+ threadRecyclingSemaphore.release();
+ }
+};
+
+/*
+ Test that the thread pool really reuses threads.
+*/
+void tst_QThreadPool::threadRecycling()
+{
+ QThreadPool threadPool;
+
+ threadPool.start(new ThreadRecorderTask());
+ threadRecyclingSemaphore.acquire();
+ QThread *thread1 = recycledThread;
+
+ QTest::qSleep(100);
+
+ threadPool.start(new ThreadRecorderTask());
+ threadRecyclingSemaphore.acquire();
+ QThread *thread2 = recycledThread;
+ QCOMPARE(thread1, thread2);
+
+ QTest::qSleep(100);
+
+ threadPool.start(new ThreadRecorderTask());
+ threadRecyclingSemaphore.acquire();
+ QThread *thread3 = recycledThread;
+ QCOMPARE(thread2, thread3);
+}
+
+class ExpiryTimeoutTask : public QRunnable
+{
+public:
+ QThread *thread;
+ int runCount;
+ QSemaphore semaphore;
+
+ ExpiryTimeoutTask()
+ : thread(0), runCount(0)
+ {
+ setAutoDelete(false);
+ }
+
+ void run()
+ {
+ thread = QThread::currentThread();
+ ++runCount;
+ semaphore.release();
+ }
+};
+
+void tst_QThreadPool::expiryTimeout()
+{
+ ExpiryTimeoutTask task;
+
+ QThreadPool threadPool;
+ threadPool.setMaxThreadCount(1);
+
+ int expiryTimeout = threadPool.expiryTimeout();
+ threadPool.setExpiryTimeout(1000);
+ QCOMPARE(threadPool.expiryTimeout(), 1000);
+
+ // run the task
+ threadPool.start(&task);
+ QVERIFY(task.semaphore.tryAcquire(1, 10000));
+ QCOMPARE(task.runCount, 1);
+ QVERIFY(!task.thread->wait(100));
+ // thread should expire
+ QThread *firstThread = task.thread;
+ QVERIFY(task.thread->wait(10000));
+
+ // run task again, thread should be restarted
+ threadPool.start(&task);
+ QVERIFY(task.semaphore.tryAcquire(1, 10000));
+ QCOMPARE(task.runCount, 2);
+ QVERIFY(!task.thread->wait(100));
+ // thread should expire again
+ QVERIFY(task.thread->wait(10000));
+
+ // thread pool should have reused the expired thread (instead of
+ // starting a new one)
+ QCOMPARE(firstThread, task.thread);
+
+ threadPool.setExpiryTimeout(expiryTimeout);
+ QCOMPARE(threadPool.expiryTimeout(), expiryTimeout);
+}
+
+#ifndef QT_NO_EXCEPTIONS
+class ExceptionTask : public QRunnable
+{
+public:
+ void run()
+ {
+ throw new int;
+ }
+};
+#endif
+
+void tst_QThreadPool::exceptions()
+{
+#ifndef QT_NO_EXCEPTIONS
+ ExceptionTask task;
+ {
+ QThreadPool threadPool;
+// Uncomment this for a nice crash.
+// threadPool.start(&task);
+ }
+#else
+ QSKIP("No exception support", SkipAll);
+#endif
+}
+
+void tst_QThreadPool::maxThreadCount()
+{
+ DEPENDS_ON("setMaxThreadCount()");
+}
+
+void tst_QThreadPool::setMaxThreadCount_data()
+{
+ QTest::addColumn<int>("limit");
+
+ QTest::newRow("") << 1;
+ QTest::newRow("") << -1;
+ QTest::newRow("") << 2;
+ QTest::newRow("") << -2;
+ QTest::newRow("") << 4;
+ QTest::newRow("") << -4;
+ QTest::newRow("") << 0;
+ QTest::newRow("") << 12345;
+ QTest::newRow("") << -6789;
+ QTest::newRow("") << 42;
+ QTest::newRow("") << -666;
+}
+
+void tst_QThreadPool::setMaxThreadCount()
+{
+ QFETCH(int, limit);
+ QThreadPool *threadPool = QThreadPool::globalInstance();
+ int savedLimit = threadPool->maxThreadCount();
+
+ // maxThreadCount() should always return the previous argument to
+ // setMaxThreadCount(), regardless of input
+ threadPool->setMaxThreadCount(limit);
+ QCOMPARE(threadPool->maxThreadCount(), limit);
+
+ // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount()
+ threadPool->setMaxThreadCount(savedLimit);
+ QCOMPARE(threadPool->maxThreadCount(), savedLimit);
+
+ // setting the limit on children should have no effect on the parent
+ {
+ QThreadPool threadPool2(threadPool);
+ savedLimit = threadPool2.maxThreadCount();
+
+ // maxThreadCount() should always return the previous argument to
+ // setMaxThreadCount(), regardless of input
+ threadPool2.setMaxThreadCount(limit);
+ QCOMPARE(threadPool2.maxThreadCount(), limit);
+
+ // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount()
+ threadPool2.setMaxThreadCount(savedLimit);
+ QCOMPARE(threadPool2.maxThreadCount(), savedLimit);
+ }
+}
+
+void tst_QThreadPool::setMaxThreadCountStartsAndStopsThreads()
+{
+ class WaitingTask : public QRunnable
+ {
+ public:
+ QSemaphore waitForStarted, waitToFinish;
+
+ WaitingTask() { setAutoDelete(false); }
+
+ void run()
+ {
+ waitForStarted.release();
+ waitToFinish.acquire();
+ }
+ };
+
+ QThreadPool threadPool;
+ threadPool.setMaxThreadCount(1);
+
+ WaitingTask *task = new WaitingTask;
+ threadPool.start(task);
+ QVERIFY(task->waitForStarted.tryAcquire(1, 1000));
+
+ // thread limit is 1, cannot start more tasks
+ threadPool.start(task);
+ QVERIFY(!task->waitForStarted.tryAcquire(1, 1000));
+
+ // increasing the limit by 1 should start the task immediately
+ threadPool.setMaxThreadCount(2);
+ QVERIFY(task->waitForStarted.tryAcquire(1, 1000));
+
+ // ... but we still cannot start more tasks
+ threadPool.start(task);
+ QVERIFY(!task->waitForStarted.tryAcquire(1, 1000));
+
+ // increasing the limit should be able to start more than one at a time
+ threadPool.start(task);
+ threadPool.setMaxThreadCount(4);
+ QVERIFY(task->waitForStarted.tryAcquire(2, 1000));
+
+ // ... but we still cannot start more tasks
+ threadPool.start(task);
+ threadPool.start(task);
+ QVERIFY(!task->waitForStarted.tryAcquire(2, 1000));
+
+ // decreasing the thread limit should cause the active thread count to go down
+ threadPool.setMaxThreadCount(2);
+ QCOMPARE(threadPool.activeThreadCount(), 4);
+ task->waitToFinish.release(2);
+ QTest::qWait(1000);
+ QCOMPARE(threadPool.activeThreadCount(), 2);
+
+ // ... and we still cannot start more tasks
+ threadPool.start(task);
+ threadPool.start(task);
+ QVERIFY(!task->waitForStarted.tryAcquire(2, 1000));
+
+ // start all remaining tasks
+ threadPool.start(task);
+ threadPool.start(task);
+ threadPool.start(task);
+ threadPool.start(task);
+ threadPool.setMaxThreadCount(8);
+ QVERIFY(task->waitForStarted.tryAcquire(6, 1000));
+
+ task->waitToFinish.release(10);
+// delete task;
+}
+
+
+void tst_QThreadPool::activeThreadCount()
+{
+ DEPENDS_ON("tryReserveThread()");
+ DEPENDS_ON("reserveThread()");
+ DEPENDS_ON("releaseThread()");
+}
+
+void tst_QThreadPool::reserveThread_data()
+{
+ setMaxThreadCount_data();
+}
+
+void tst_QThreadPool::reserveThread()
+{
+ QFETCH(int, limit);
+ QThreadPool *threadpool = QThreadPool::globalInstance();
+ int savedLimit = threadpool->maxThreadCount();
+ threadpool->setMaxThreadCount(limit);
+
+ // reserve up to the limit
+ for (int i = 0; i < limit; ++i)
+ threadpool->reserveThread();
+
+ // reserveThread() should always reserve a thread, regardless of
+ // how many have been previously reserved
+ threadpool->reserveThread();
+ QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 1);
+ threadpool->reserveThread();
+ QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 2);
+
+ // cleanup
+ threadpool->releaseThread();
+ threadpool->releaseThread();
+ for (int i = 0; i < limit; ++i)
+ threadpool->releaseThread();
+
+ // reserving threads in children should not effect the parent
+ {
+ QThreadPool threadpool2(threadpool);
+ threadpool2.setMaxThreadCount(limit);
+
+ // reserve up to the limit
+ for (int i = 0; i < limit; ++i)
+ threadpool2.reserveThread();
+
+ // reserveThread() should always reserve a thread, regardless
+ // of how many have been previously reserved
+ threadpool2.reserveThread();
+ QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 1);
+ threadpool2.reserveThread();
+ QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 2);
+
+ threadpool->reserveThread();
+ QCOMPARE(threadpool->activeThreadCount(), 1);
+ threadpool->reserveThread();
+ QCOMPARE(threadpool->activeThreadCount(), 2);
+
+ // cleanup
+ threadpool2.releaseThread();
+ threadpool2.releaseThread();
+ threadpool->releaseThread();
+ threadpool->releaseThread();
+ while (threadpool2.activeThreadCount() > 0)
+ threadpool2.releaseThread();
+ }
+
+ // reset limit on global QThreadPool
+ threadpool->setMaxThreadCount(savedLimit);
+}
+
+void tst_QThreadPool::releaseThread_data()
+{
+ setMaxThreadCount_data();
+}
+
+void tst_QThreadPool::releaseThread()
+{
+ QFETCH(int, limit);
+ QThreadPool *threadpool = QThreadPool::globalInstance();
+ int savedLimit = threadpool->maxThreadCount();
+ threadpool->setMaxThreadCount(limit);
+
+ // reserve up to the limit
+ for (int i = 0; i < limit; ++i)
+ threadpool->reserveThread();
+
+ // release should decrease the number of reserved threads
+ int reserved = threadpool->activeThreadCount();
+ while (reserved-- > 0) {
+ threadpool->releaseThread();
+ QCOMPARE(threadpool->activeThreadCount(), reserved);
+ }
+ QCOMPARE(threadpool->activeThreadCount(), 0);
+
+ // releaseThread() can release more than have been reserved
+ threadpool->releaseThread();
+ QCOMPARE(threadpool->activeThreadCount(), -1);
+ threadpool->reserveThread();
+ QCOMPARE(threadpool->activeThreadCount(), 0);
+
+ // releasing threads in children should not effect the parent
+ {
+ QThreadPool threadpool2(threadpool);
+ threadpool2.setMaxThreadCount(limit);
+
+ // reserve up to the limit
+ for (int i = 0; i < limit; ++i)
+ threadpool2.reserveThread();
+
+ // release should decrease the number of reserved threads
+ int reserved = threadpool2.activeThreadCount();
+ while (reserved-- > 0) {
+ threadpool2.releaseThread();
+ QCOMPARE(threadpool2.activeThreadCount(), reserved);
+ QCOMPARE(threadpool->activeThreadCount(), 0);
+ }
+ QCOMPARE(threadpool2.activeThreadCount(), 0);
+ QCOMPARE(threadpool->activeThreadCount(), 0);
+
+ // releaseThread() can release more than have been reserved
+ threadpool2.releaseThread();
+ QCOMPARE(threadpool2.activeThreadCount(), -1);
+ QCOMPARE(threadpool->activeThreadCount(), 0);
+ threadpool2.reserveThread();
+ QCOMPARE(threadpool2.activeThreadCount(), 0);
+ QCOMPARE(threadpool->activeThreadCount(), 0);
+ }
+
+ // reset limit on global QThreadPool
+ threadpool->setMaxThreadCount(savedLimit);
+}
+
+QAtomicInt count;
+class CountingRunnable : public QRunnable
+{
+ public: void run()
+ {
+ count.ref();
+ }
+};
+
+void tst_QThreadPool::start()
+{
+ const int runs = 1000;
+ count = 0;
+ {
+ QThreadPool threadPool;
+ for (int i = 0; i< runs; ++i) {
+ threadPool.start(new CountingRunnable());
+ }
+ }
+ QCOMPARE(int(count), runs);
+}
+
+void tst_QThreadPool::tryStart()
+{
+ class WaitingTask : public QRunnable
+ {
+ public:
+ QSemaphore semaphore;
+
+ WaitingTask() { setAutoDelete(false); }
+
+ void run()
+ {
+ semaphore.acquire();
+ count.ref();
+ }
+ };
+
+ count = 0;
+
+ WaitingTask task;
+ QThreadPool threadPool;
+ for (int i = 0; i < threadPool.maxThreadCount(); ++i) {
+ threadPool.start(&task);
+ }
+ QVERIFY(!threadPool.tryStart(&task));
+ task.semaphore.release(threadPool.maxThreadCount());
+ threadPool.waitForDone();
+ QCOMPARE(int(count), threadPool.maxThreadCount());
+}
+
+QMutex mutex;
+int activeThreads = 0;
+int peakActiveThreads = 0;
+void tst_QThreadPool::tryStartPeakThreadCount()
+{
+ class CounterTask : public QRunnable
+ {
+ public:
+ CounterTask() { setAutoDelete(false); }
+
+ void run()
+ {
+ {
+ QMutexLocker lock(&mutex);
+ ++activeThreads;
+ peakActiveThreads = qMax(peakActiveThreads, activeThreads);
+ }
+
+ QTest::qWait(100);
+ {
+ QMutexLocker lock(&mutex);
+ --activeThreads;
+ }
+ }
+ };
+
+ CounterTask task;
+ QThreadPool threadPool;
+
+ for (int i = 0; i < 20; ++i) {
+ if (threadPool.tryStart(&task) == false)
+ QTest::qWait(10);
+ }
+ QCOMPARE(peakActiveThreads, QThread::idealThreadCount());
+
+ for (int i = 0; i < 20; ++i) {
+ if (threadPool.tryStart(&task) == false)
+ QTest::qWait(10);
+ }
+ QCOMPARE(peakActiveThreads, QThread::idealThreadCount());
+}
+
+void tst_QThreadPool::tryStartCount()
+{
+ class SleeperTask : public QRunnable
+ {
+ public:
+ SleeperTask() { setAutoDelete(false); }
+
+ void run()
+ {
+ QTest::qWait(50);
+ }
+ };
+
+ SleeperTask task;
+ QThreadPool threadPool;
+ const int runs = 5;
+
+ for (int i = 0; i < runs; ++i) {
+// qDebug() << "iteration" << i;
+ int count = 0;
+ while (threadPool.tryStart(&task))
+ ++count;
+ QCOMPARE(count, QThread::idealThreadCount());
+
+ QTest::qWait(100);
+ }
+}
+
+void tst_QThreadPool::waitForDone()
+{
+ QTime total, pass;
+ total.start();
+
+ QThreadPool threadPool;
+ while (total.elapsed() < 10000) {
+ int runs;
+ runs = count = 0;
+ pass.restart();
+ while (pass.elapsed() < 100) {
+ threadPool.start(new CountingRunnable());
+ ++runs;
+ }
+ threadPool.waitForDone();
+ QCOMPARE(int(count), runs);
+
+ runs = count = 0;
+ pass.restart();
+ while (pass.elapsed() < 100) {
+ threadPool.start(new CountingRunnable());
+ threadPool.start(new CountingRunnable());
+ runs += 2;
+ }
+ threadPool.waitForDone();
+ QCOMPARE(int(count), runs);
+ }
+}
+
+void tst_QThreadPool::waitForDoneTimeout()
+{
+ class BlockedTask : public QRunnable
+ {
+ public:
+ QMutex mutex;
+ BlockedTask() { setAutoDelete(false); }
+
+ void run()
+ {
+ mutex.lock();
+ mutex.unlock();
+ QTest::qSleep(50);
+ }
+ };
+
+ QThreadPool threadPool;
+
+ BlockedTask *task = new BlockedTask;
+ task->mutex.lock();
+ threadPool.start(task);
+ QVERIFY(!threadPool.waitForDone(100));
+ task->mutex.unlock();
+ QVERIFY(threadPool.waitForDone(400));
+}
+
+void tst_QThreadPool::destroyingWaitsForTasksToFinish()
+{
+ QTime total, pass;
+ total.start();
+
+ while (total.elapsed() < 10000) {
+ int runs;
+ runs = count = 0;
+ {
+ QThreadPool threadPool;
+ pass.restart();
+ while (pass.elapsed() < 100) {
+ threadPool.start(new CountingRunnable());
+ ++runs;
+ }
+ }
+ QCOMPARE(int(count), runs);
+
+ runs = count = 0;
+ {
+ QThreadPool threadPool;
+ pass.restart();
+ while (pass.elapsed() < 100) {
+ threadPool.start(new CountingRunnable());
+ threadPool.start(new CountingRunnable());
+ runs += 2;
+ }
+ }
+ QCOMPARE(int(count), runs);
+ }
+}
+
+void tst_QThreadPool::stressTest()
+{
+ class Task : public QRunnable
+ {
+ QSemaphore semaphore;
+ public:
+ Task() { setAutoDelete(false); }
+
+ void start()
+ {
+ QThreadPool::globalInstance()->start(this);
+ }
+
+ void wait()
+ {
+ semaphore.acquire();
+ }
+
+ void run()
+ {
+ semaphore.release();
+ }
+ };
+
+ QTime total;
+ total.start();
+ while (total.elapsed() < 30000) {
+ Task t;
+ t.start();
+ t.wait();
+ }
+}
+
+QTEST_MAIN(tst_QThreadPool);
+#include "tst_qthreadpool.moc"