From 559a72e4b637b9abb059e2708f206bbaca2be9e2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 31 Jul 2014 14:09:11 +0200 Subject: [PATCH] QtConcurrent::run: allow to select the thread pool on which to run the task This is the second and last part of the forward-port of https://qt.gitorious.org/qt/qt/merge_requests/1281 [ChangeLog][QtConcurrent] run() now optionally takes as its first argument the QThreadPool to run the task on. Task-number: QTBUG-17220 Change-Id: I4b46eca6ef7de9cd34dac07e6d4b8ad830426b97 Reviewed-by: Olivier Goffart --- .../code/src_concurrent_qtconcurrentrun.cpp | 7 + src/concurrent/qtconcurrentrun.cpp | 31 +- src/concurrent/qtconcurrentrun.h | 274 ++++++++++++++++++ src/concurrent/qtconcurrentrunbase.h | 8 +- .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 130 ++++++++- 5 files changed, 445 insertions(+), 5 deletions(-) diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp index 8922e41f34..ab7c67d4fb 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp @@ -44,6 +44,13 @@ QFuture future = QtConcurrent::run(aFunction); //! [0] +//! [explicit-pool-0] +extern void aFunction(); +QThreadPool pool; +QFuture future = QtConcurrent::run(&pool, aFunction); +//! [explicit-pool-0] + + //! [1] extern void aFunctionWithArguments(int arg1, double arg2, const QString &string); diff --git a/src/concurrent/qtconcurrentrun.cpp b/src/concurrent/qtconcurrentrun.cpp index c71fc9048f..0b557f054c 100644 --- a/src/concurrent/qtconcurrentrun.cpp +++ b/src/concurrent/qtconcurrentrun.cpp @@ -59,6 +59,11 @@ QThreadPool. You can use the QFuture and QFutureWatcher classes to monitor the status of the function. + To use a dedicated thread pool, you can pass the QThreadPool as + the first argument: + + \snippet code/src_concurrent_qtconcurrentrun.cpp explicit-pool-0 + \section1 Passing Arguments to the Function Passing arguments to the function is done by adding them to the @@ -130,9 +135,31 @@ /*! \fn QFuture QtConcurrent::run(Function function, ...); + Equivalent to + \code + QtConcurrent::run(QThreadPool::globalInstance(), function, ...); + \endcode + Runs \a function in a separate thread. The thread is taken from the global - QThreadPool. Note that the function may not run immediately; the function - will only be run when a thread is available. + QThreadPool. Note that \a function may not run immediately; \a function + will only be run once a thread becomes available. + + T is the same type as the return value of \a function. Non-void return + values can be accessed via the QFuture::result() function. + + Note that the QFuture returned by QtConcurrent::run() does not support + canceling, pausing, or progress reporting. The QFuture returned can only + be used to query for the running/finished status and the return value of + the function. +*/ + +/*! + \since 5.4 + \fn QFuture QtConcurrent::run(QThreadPool *pool, Function function, ...); + + Runs \a function in a separate thread. The thread is taken from the + QThreadPool \a pool. Note that \a function may not run immediately; \a function + will only be run once a thread becomes available. T is the same type as the return value of \a function. Non-void return values can be accessed via the QFuture::result() function. diff --git a/src/concurrent/qtconcurrentrun.h b/src/concurrent/qtconcurrentrun.h index 0bfe4bfd0a..de6ebbf0c0 100644 --- a/src/concurrent/qtconcurrentrun.h +++ b/src/concurrent/qtconcurrentrun.h @@ -60,6 +60,9 @@ namespace QtConcurrent { template QFuture run(Function function, ...); + template + QFuture run(QThreadPool *pool, Function function, ...); + } // namespace QtConcurrent #else @@ -334,6 +337,277 @@ QFuture run(const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param return (new typename SelectStoredConstMemberFunctionPointerCall5::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(); } +// ...and the same with a QThreadPool *pool argument... +// generate from the above by c'n'p and s/run(/run(QThreadPool *pool, / and s/start()/start(pool)/ + +template +QFuture run(QThreadPool *pool, T (*functionPointer)()) +{ + return (new StoredFunctorCall0(functionPointer))->start(pool); +} +template +QFuture run(QThreadPool *pool, T (*functionPointer)(Param1), const Arg1 &arg1) +{ + return (new StoredFunctorCall1(functionPointer, arg1))->start(pool); +} +template +QFuture run(QThreadPool *pool, T (*functionPointer)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2) +{ + return (new StoredFunctorCall2(functionPointer, arg1, arg2))->start(pool); +} +template +QFuture run(QThreadPool *pool, T (*functionPointer)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + return (new StoredFunctorCall3(functionPointer, arg1, arg2, arg3))->start(pool); +} +template +QFuture run(QThreadPool *pool, T (*functionPointer)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + return (new StoredFunctorCall4(functionPointer, arg1, arg2, arg3, arg4))->start(pool); +} +template +QFuture run(QThreadPool *pool, T (*functionPointer)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + return (new StoredFunctorCall5(functionPointer, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + +#if defined(Q_COMPILER_DECLTYPE) && defined(Q_COMPILER_AUTO_FUNCTION) + +template +auto run(QThreadPool *pool, Functor functor) -> typename QtPrivate::QEnableIf::Value, QFuture >::Type +{ + typedef decltype(functor()) result_type; + return (new StoredFunctorCall0(functor))->start(pool); +} + +template +auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1) + -> typename QtPrivate::QEnableIf::Value, QFuture >::Type +{ + typedef decltype(functor(arg1)) result_type; + return (new StoredFunctorCall1(functor, arg1))->start(pool); +} + +template +auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2) + -> typename QtPrivate::QEnableIf::Value, QFuture >::Type +{ + typedef decltype(functor(arg1, arg2)) result_type; + return (new StoredFunctorCall2(functor, arg1, arg2))->start(pool); +} + +template +auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) + -> typename QtPrivate::QEnableIf::Value, QFuture >::Type +{ + typedef decltype(functor(arg1, arg2, arg3)) result_type; + return (new StoredFunctorCall3(functor, arg1, arg2, arg3))->start(pool); +} + +template +auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) + -> typename QtPrivate::QEnableIf::Value, QFuture >::Type +{ + typedef decltype(functor(arg1, arg2, arg3, arg4)) result_type; + return (new StoredFunctorCall4(functor, arg1, arg2, arg3, arg4))->start(pool); +} + +template +auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) + -> typename QtPrivate::QEnableIf::Value, QFuture >::Type +{ + typedef decltype(functor(arg1, arg2, arg3, arg4, arg5)) result_type; + return (new StoredFunctorCall5(functor, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + +#endif + +template +QFuture run(QThreadPool *pool, FunctionObject functionObject) +{ + return (new StoredFunctorCall0(functionObject))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1) +{ + return (new StoredFunctorCall1(functionObject, arg1))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2) +{ + return (new StoredFunctorCall2(functionObject, arg1, arg2))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + return (new StoredFunctorCall3(functionObject, arg1, arg2, arg3))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + return (new StoredFunctorCall4(functionObject, arg1, arg2, arg3, arg4))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + return (new StoredFunctorCall5(functionObject, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + +template +QFuture run(QThreadPool *pool, FunctionObject *functionObject) +{ + return (new typename SelectStoredFunctorPointerCall0::type(functionObject))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1) +{ + return (new typename SelectStoredFunctorPointerCall1::type(functionObject, arg1))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2) +{ + return (new typename SelectStoredFunctorPointerCall2::type(functionObject, arg1, arg2))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + return (new typename SelectStoredFunctorPointerCall3::type(functionObject, arg1, arg2, arg3))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + return (new typename SelectStoredFunctorPointerCall4::type(functionObject, arg1, arg2, arg3, arg4))->start(pool); +} +template +QFuture run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + return (new typename SelectStoredFunctorPointerCall5::type(functionObject, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)()) +{ + return (new typename SelectStoredMemberFunctionCall0::type(fn, object))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1), const Arg1 &arg1) +{ + return (new typename SelectStoredMemberFunctionCall1::type(fn, object, arg1))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2) +{ + return (new typename SelectStoredMemberFunctionCall2::type(fn, object, arg1, arg2))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + return (new typename SelectStoredMemberFunctionCall3::type(fn, object, arg1, arg2, arg3))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + return (new typename SelectStoredMemberFunctionCall4::type(fn, object, arg1, arg2, arg3, arg4))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + return (new typename SelectStoredMemberFunctionCall5::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)() const) +{ + return (new typename SelectStoredConstMemberFunctionCall0::type(fn, object))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1) const, const Arg1 &arg1) +{ + return (new typename SelectStoredConstMemberFunctionCall1::type(fn, object, arg1))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2) +{ + return (new typename SelectStoredConstMemberFunctionCall2::type(fn, object, arg1, arg2))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2, Param3) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + return (new typename SelectStoredConstMemberFunctionCall3::type(fn, object, arg1, arg2, arg3))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + return (new typename SelectStoredConstMemberFunctionCall4::type(fn, object, arg1, arg2, arg3, arg4))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + return (new typename SelectStoredConstMemberFunctionCall5::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + +template +QFuture run(QThreadPool *pool, Class *object, T (Class::*fn)()) +{ + return (new typename SelectStoredMemberFunctionPointerCall0::type(fn, object))->start(pool); +} +template +QFuture run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1), const Arg1 &arg1) +{ + return (new typename SelectStoredMemberFunctionPointerCall1::type(fn, object, arg1))->start(pool); +} +template +QFuture run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2) +{ + return (new typename SelectStoredMemberFunctionPointerCall2::type(fn, object, arg1, arg2))->start(pool); +} +template +QFuture run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + return (new typename SelectStoredMemberFunctionPointerCall3::type(fn, object, arg1, arg2, arg3))->start(pool); +} +template +QFuture run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + return (new typename SelectStoredMemberFunctionPointerCall4::type(fn, object, arg1, arg2, arg3, arg4))->start(pool); +} +template +QFuture run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + return (new typename SelectStoredMemberFunctionPointerCall5::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + +template +QFuture run(QThreadPool *pool, const Class *object, T (Class::*fn)() const) +{ + return (new typename SelectStoredConstMemberFunctionPointerCall0::type(fn, object))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class *object, T (Class::*fn)(Param1) const, const Arg1 &arg1) +{ + return (new typename SelectStoredConstMemberFunctionPointerCall1::type(fn, object, arg1))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class *object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2) +{ + return (new typename SelectStoredConstMemberFunctionPointerCall2::type(fn, object, arg1, arg2))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class *object, T (Class::*fn)(Param1, Param2, Param3) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + return (new typename SelectStoredConstMemberFunctionPointerCall3::type(fn, object, arg1, arg2, arg3))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + return (new typename SelectStoredConstMemberFunctionPointerCall4::type(fn, object, arg1, arg2, arg3, arg4))->start(pool); +} +template +QFuture run(QThreadPool *pool, const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + return (new typename SelectStoredConstMemberFunctionPointerCall5::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool); +} + } //namespace QtConcurrent #endif // Q_QDOC diff --git a/src/concurrent/qtconcurrentrunbase.h b/src/concurrent/qtconcurrentrunbase.h index bd24c42ce2..ae638e5709 100644 --- a/src/concurrent/qtconcurrentrunbase.h +++ b/src/concurrent/qtconcurrentrunbase.h @@ -77,10 +77,16 @@ class RunFunctionTaskBase : public QFutureInterface , public QRunnable public: QFuture start() { + return start(QThreadPool::globalInstance()); + } + + QFuture start(QThreadPool *pool) + { + this->setThreadPool(pool); this->setRunnable(this); this->reportStarted(); QFuture theFuture = this->future(); - QThreadPool::globalInstance()->start(this, /*m_priority*/ 0); + pool->start(this, /*m_priority*/ 0); return theFuture; } diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp index 8a289ff4e1..75b5af2421 100644 --- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp +++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -95,8 +95,9 @@ void tst_QtConcurrentRun::runLightFunction() void tst_QtConcurrentRun::runHeavyFunction() { + QThreadPool pool; qDebug("starting function"); - QFuture future = run(heavy); + QFuture future = run(&pool, heavy); qDebug("waiting"); future.waitForFinished(); qDebug("done"); @@ -136,60 +137,95 @@ public: void tst_QtConcurrentRun::returnValue() { + QThreadPool pool; QFuture f; f = run(returnInt0); QCOMPARE(f.result(), 10); + f = run(&pool, returnInt0); + QCOMPARE(f.result(), 10); A a; f = run(&a, &A::member0); QCOMPARE(f.result(), 10); + f = run(&pool, &a, &A::member0); + QCOMPARE(f.result(), 10); f = run(&a, &A::member1, 20); QCOMPARE(f.result(), 20); + f = run(&pool, &a, &A::member1, 20); + QCOMPARE(f.result(), 20); f = run(a, &A::member0); QCOMPARE(f.result(), 10); + f = run(&pool, a, &A::member0); + QCOMPARE(f.result(), 10); f = run(a, &A::member1, 20); QCOMPARE(f.result(), 20); + f = run(&pool, a, &A::member1, 20); + QCOMPARE(f.result(), 20); f = run(a); QCOMPARE(f.result(), 10); + f = run(&pool, a); + QCOMPARE(f.result(), 10); f = run(&a); QCOMPARE(f.result(), 10); + f = run(&pool, &a); + QCOMPARE(f.result(), 10); f = run(a, 20); QCOMPARE(f.result(), 20); + f = run(&pool, a, 20); + QCOMPARE(f.result(), 20); f = run(&a, 20); QCOMPARE(f.result(), 20); + f = run(&pool, &a, 20); + QCOMPARE(f.result(), 20); const AConst aConst = AConst(); f = run(&aConst, &AConst::member0); QCOMPARE(f.result(), 10); + f = run(&pool, &aConst, &AConst::member0); + QCOMPARE(f.result(), 10); f = run(&aConst, &AConst::member1, 20); QCOMPARE(f.result(), 20); + f = run(&pool, &aConst, &AConst::member1, 20); + QCOMPARE(f.result(), 20); f = run(aConst, &AConst::member0); QCOMPARE(f.result(), 10); + f = run(&pool, aConst, &AConst::member0); + QCOMPARE(f.result(), 10); f = run(aConst, &AConst::member1, 20); QCOMPARE(f.result(), 20); + f = run(&pool, aConst, &AConst::member1, 20); + QCOMPARE(f.result(), 20); f = run(aConst); QCOMPARE(f.result(), 10); + f = run(&pool, aConst); + QCOMPARE(f.result(), 10); f = run(&aConst); QCOMPARE(f.result(), 10); + f = run(&pool, &aConst); + QCOMPARE(f.result(), 10); f = run(aConst, 20); QCOMPARE(f.result(), 20); + f = run(&pool, aConst, 20); + QCOMPARE(f.result(), 20); f = run(&aConst, 20); QCOMPARE(f.result(), 20); + f = run(&pool, &aConst, 20); + QCOMPARE(f.result(), 20); } struct TestClass @@ -212,6 +248,7 @@ struct TestConstClass void tst_QtConcurrentRun::functionObject() { + QThreadPool pool; QFuture f; TestClass c; @@ -220,16 +257,28 @@ void tst_QtConcurrentRun::functionObject() f = run(c, 10); f = run(&c, 10); + f = run(&pool, c); + f = run(&pool, &c); + f = run(&pool, c, 10); + f = run(&pool, &c, 10); + const TestConstClass cc = TestConstClass(); f = run(cc); f = run(&cc); f = run(cc, 10); f = run(&cc, 10); + + f = run(&pool, cc); + f = run(&pool, &cc); + f = run(&pool, cc, 10); + f = run(&pool, &cc, 10); } void tst_QtConcurrentRun::memberFunctions() { + QThreadPool pool; + TestClass c; run(c, &TestClass::foo).waitForFinished(); @@ -237,11 +286,21 @@ void tst_QtConcurrentRun::memberFunctions() run(c, &TestClass::fooInt, 10).waitForFinished(); run(&c, &TestClass::fooInt, 10).waitForFinished(); + run(&pool, c, &TestClass::foo).waitForFinished(); + run(&pool, &c, &TestClass::foo).waitForFinished(); + run(&pool, c, &TestClass::fooInt, 10).waitForFinished(); + run(&pool, &c, &TestClass::fooInt, 10).waitForFinished(); + const TestConstClass cc = TestConstClass(); run(cc, &TestConstClass::foo).waitForFinished(); run(&cc, &TestConstClass::foo).waitForFinished(); run(cc, &TestConstClass::fooInt, 10).waitForFinished(); run(&cc, &TestConstClass::fooInt, 10).waitForFinished(); + + run(&pool, cc, &TestConstClass::foo).waitForFinished(); + run(&pool, &cc, &TestConstClass::foo).waitForFinished(); + run(&pool, cc, &TestConstClass::fooInt, 10).waitForFinished(); + run(&pool, &cc, &TestConstClass::fooInt, 10).waitForFinished(); } @@ -273,16 +332,25 @@ void stringIntFunction(QString) void tst_QtConcurrentRun::implicitConvertibleTypes() { + QThreadPool pool; + double d; run(doubleFunction, d).waitForFinished(); + run(&pool, doubleFunction, d).waitForFinished(); int i; run(doubleFunction, d).waitForFinished(); + run(&pool, doubleFunction, d).waitForFinished(); run(doubleFunction, i).waitForFinished(); + run(&pool, doubleFunction, i).waitForFinished(); run(doubleFunction, 10).waitForFinished(); + run(&pool, doubleFunction, 10).waitForFinished(); run(stringFunction, QLatin1String("Foo")).waitForFinished(); + run(&pool, stringFunction, QLatin1String("Foo")).waitForFinished(); run(stringConstRefFunction, QLatin1String("Foo")).waitForFinished(); + run(&pool, stringConstRefFunction, QLatin1String("Foo")).waitForFinished(); QString string; run(stringRefFunction, string).waitForFinished(); + run(&pool, stringRefFunction, string).waitForFinished(); } void fn() { } @@ -382,7 +450,10 @@ int throwFunctionReturn() void tst_QtConcurrentRun::exceptions() { - bool caught = false; + QThreadPool pool; + bool caught; + + caught = false; try { QtConcurrent::run(throwFunction).waitForFinished(); } catch (QException &) { @@ -391,6 +462,15 @@ void tst_QtConcurrentRun::exceptions() if (!caught) QFAIL("did not get exception"); + caught = false; + try { + QtConcurrent::run(&pool, throwFunction).waitForFinished(); + } catch (QException &) { + caught = true; + } + if (!caught) + QFAIL("did not get exception"); + caught = false; try { QtConcurrent::run(throwFunctionReturn).waitForFinished(); @@ -399,6 +479,15 @@ void tst_QtConcurrentRun::exceptions() } if (!caught) QFAIL("did not get exception"); + + caught = false; + try { + QtConcurrent::run(&pool, throwFunctionReturn).waitForFinished(); + } catch (QException &) { + caught = true; + } + if (!caught) + QFAIL("did not get exception"); } #endif @@ -438,6 +527,27 @@ void tst_QtConcurrentRun::functor() QtConcurrent::run(f, 1,2,3,4).waitForFinished(); QtConcurrent::run(f, 1,2,3,4,5).waitForFinished(); } + // and now with explicit pool: + QThreadPool pool; + { + QFuture fut = QtConcurrent::run(&pool, f); + QCOMPARE(fut.result(), 42); + } + { + QFuture fut = QtConcurrent::run(&pool, f, 8.5, 1.8); + QCOMPARE(fut.result(), (8.5/1.8)); + } + { + QFuture fut = QtConcurrent::run(&pool, f, 19, 3); + QCOMPARE(fut.result(), int(19/3)); + } + { + QtConcurrent::run(&pool, f, 1).waitForFinished(); + QtConcurrent::run(&pool, f, 1,2).waitForFinished(); + QtConcurrent::run(&pool, f, 1,2,3).waitForFinished(); + QtConcurrent::run(&pool, f, 1,2,3,4).waitForFinished(); + QtConcurrent::run(&pool, f, 1,2,3,4,5).waitForFinished(); + } } #endif @@ -458,6 +568,22 @@ void tst_QtConcurrentRun::lambda() QCOMPARE(r, QStringList({"Hello", "World", "Foo"})); } #endif + + // and now with explicit pool: + QThreadPool pool; + QCOMPARE(QtConcurrent::run(&pool, [](){ return 45; }).result(), 45); + QCOMPARE(QtConcurrent::run(&pool, [](int a){ return a+15; }, 12).result(), 12+15); + QCOMPARE(QtConcurrent::run(&pool, [](int a, double b){ return a + b; }, 12, 15).result(), double(12+15)); + QCOMPARE(QtConcurrent::run(&pool, [](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 f1 = QtConcurrent::run(&pool, [&](){ return str.split(' '); }); + auto r = f1.result(); + QCOMPARE(r, QStringList({"Hello", "World", "Foo"})); + } +#endif } #endif