From 559a72e4b637b9abb059e2708f206bbaca2be9e2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 31 Jul 2014 14:09:11 +0200 Subject: 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 +- 4 files changed, 317 insertions(+), 3 deletions(-) (limited to 'src/concurrent') 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; } -- cgit v1.2.3