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 <ogoffart@woboq.com>
This commit is contained in:
Marc Mutz 2014-07-31 14:09:11 +02:00
parent c55aec2ed7
commit 559a72e4b6
5 changed files with 445 additions and 5 deletions

View File

@ -44,6 +44,13 @@ QFuture<void> future = QtConcurrent::run(aFunction);
//! [0] //! [0]
//! [explicit-pool-0]
extern void aFunction();
QThreadPool pool;
QFuture<void> future = QtConcurrent::run(&pool, aFunction);
//! [explicit-pool-0]
//! [1] //! [1]
extern void aFunctionWithArguments(int arg1, double arg2, const QString &string); extern void aFunctionWithArguments(int arg1, double arg2, const QString &string);

View File

@ -59,6 +59,11 @@
QThreadPool. You can use the QFuture and QFutureWatcher classes to monitor QThreadPool. You can use the QFuture and QFutureWatcher classes to monitor
the status of the function. 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 \section1 Passing Arguments to the Function
Passing arguments to the function is done by adding them to the Passing arguments to the function is done by adding them to the
@ -130,9 +135,31 @@
/*! /*!
\fn QFuture<T> QtConcurrent::run(Function function, ...); \fn QFuture<T> 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 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 QThreadPool. Note that \a function may not run immediately; \a function
will only be run when a thread is available. 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<T> 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 T is the same type as the return value of \a function. Non-void return
values can be accessed via the QFuture::result() function. values can be accessed via the QFuture::result() function.

View File

@ -60,6 +60,9 @@ namespace QtConcurrent {
template <typename T> template <typename T>
QFuture<T> run(Function function, ...); QFuture<T> run(Function function, ...);
template <typename T>
QFuture<T> run(QThreadPool *pool, Function function, ...);
} // namespace QtConcurrent } // namespace QtConcurrent
#else #else
@ -334,6 +337,277 @@ QFuture<T> run(const Class *object, T (Class::*fn)(Param1, Param2, Param3, Param
return (new typename SelectStoredConstMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(); return (new typename SelectStoredConstMemberFunctionPointerCall5<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::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 <typename T>
QFuture<T> run(QThreadPool *pool, T (*functionPointer)())
{
return (new StoredFunctorCall0<T, T (*)()>(functionPointer))->start(pool);
}
template <typename T, typename Param1, typename Arg1>
QFuture<T> run(QThreadPool *pool, T (*functionPointer)(Param1), const Arg1 &arg1)
{
return (new StoredFunctorCall1<T, T (*)(Param1), Arg1>(functionPointer, arg1))->start(pool);
}
template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2>
QFuture<T> run(QThreadPool *pool, T (*functionPointer)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
{
return (new StoredFunctorCall2<T, T (*)(Param1, Param2), Arg1, Arg2>(functionPointer, arg1, arg2))->start(pool);
}
template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
QFuture<T> run(QThreadPool *pool, T (*functionPointer)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
{
return (new StoredFunctorCall3<T, T (*)(Param1, Param2, Param3), Arg1, Arg2, Arg3>(functionPointer, arg1, arg2, arg3))->start(pool);
}
template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
QFuture<T> run(QThreadPool *pool, T (*functionPointer)(Param1, Param2, Param3, Param4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
{
return (new StoredFunctorCall4<T, T (*)(Param1, Param2, Param3, Param4), Arg1, Arg2, Arg3, Arg4>(functionPointer, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename T, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
QFuture<T> 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<T, T (*)(Param1, Param2, Param3, Param4, Param5), Arg1, Arg2, Arg3, Arg4, Arg5>(functionPointer, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
#if defined(Q_COMPILER_DECLTYPE) && defined(Q_COMPILER_AUTO_FUNCTION)
template <typename Functor>
auto run(QThreadPool *pool, Functor functor) -> typename QtPrivate::QEnableIf<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor())> >::Type
{
typedef decltype(functor()) result_type;
return (new StoredFunctorCall0<result_type, Functor>(functor))->start(pool);
}
template <typename Functor, typename Arg1>
auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1)
-> typename QtPrivate::QEnableIf<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor(arg1))> >::Type
{
typedef decltype(functor(arg1)) result_type;
return (new StoredFunctorCall1<result_type, Functor, Arg1>(functor, arg1))->start(pool);
}
template <typename Functor, typename Arg1, typename Arg2>
auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2)
-> typename QtPrivate::QEnableIf<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor(arg1, arg2))> >::Type
{
typedef decltype(functor(arg1, arg2)) result_type;
return (new StoredFunctorCall2<result_type, Functor, Arg1, Arg2>(functor, arg1, arg2))->start(pool);
}
template <typename Functor, typename Arg1, typename Arg2, typename Arg3>
auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
-> typename QtPrivate::QEnableIf<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor(arg1, arg2, arg3))> >::Type
{
typedef decltype(functor(arg1, arg2, arg3)) result_type;
return (new StoredFunctorCall3<result_type, Functor, Arg1, Arg2, Arg3>(functor, arg1, arg2, arg3))->start(pool);
}
template <typename Functor, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
-> typename QtPrivate::QEnableIf<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor(arg1, arg2, arg3, arg4))> >::Type
{
typedef decltype(functor(arg1, arg2, arg3, arg4)) result_type;
return (new StoredFunctorCall4<result_type, Functor, Arg1, Arg2, Arg3, Arg4>(functor, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename Functor, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
-> typename QtPrivate::QEnableIf<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor(arg1, arg2, arg3, arg4, arg5))> >::Type
{
typedef decltype(functor(arg1, arg2, arg3, arg4, arg5)) result_type;
return (new StoredFunctorCall5<result_type, Functor, Arg1, Arg2, Arg3, Arg4, Arg5>(functor, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
#endif
template <typename FunctionObject>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject functionObject)
{
return (new StoredFunctorCall0<typename FunctionObject::result_type, FunctionObject>(functionObject))->start(pool);
}
template <typename FunctionObject, typename Arg1>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1)
{
return (new StoredFunctorCall1<typename FunctionObject::result_type, FunctionObject, Arg1>(functionObject, arg1))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2)
{
return (new StoredFunctorCall2<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2>(functionObject, arg1, arg2))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
{
return (new StoredFunctorCall3<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3>(functionObject, arg1, arg2, arg3))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
{
return (new StoredFunctorCall4<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4>(functionObject, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
{
return (new StoredFunctorCall5<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4, Arg5>(functionObject, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
template <typename FunctionObject>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject *functionObject)
{
return (new typename SelectStoredFunctorPointerCall0<typename FunctionObject::result_type, FunctionObject>::type(functionObject))->start(pool);
}
template <typename FunctionObject, typename Arg1>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1)
{
return (new typename SelectStoredFunctorPointerCall1<typename FunctionObject::result_type, FunctionObject, Arg1>::type(functionObject, arg1))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2)
{
return (new typename SelectStoredFunctorPointerCall2<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2>::type(functionObject, arg1, arg2))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
{
return (new typename SelectStoredFunctorPointerCall3<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3>::type(functionObject, arg1, arg2, arg3))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
{
return (new typename SelectStoredFunctorPointerCall4<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4>::type(functionObject, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename FunctionObject, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject *functionObject, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
{
return (new typename SelectStoredFunctorPointerCall5<typename FunctionObject::result_type, FunctionObject, Arg1, Arg2, Arg3, Arg4, Arg5>::type(functionObject, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
template <typename T, typename Class>
QFuture<T> run(QThreadPool *pool, const Class &object, T (Class::*fn)())
{
return (new typename SelectStoredMemberFunctionCall0<T, Class>::type(fn, object))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1>
QFuture<T> run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1), const Arg1 &arg1)
{
return (new typename SelectStoredMemberFunctionCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
QFuture<T> run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
{
return (new typename SelectStoredMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
template <typename T, typename Class>
QFuture<T> run(QThreadPool *pool, const Class &object, T (Class::*fn)() const)
{
return (new typename SelectStoredConstMemberFunctionCall0<T, Class>::type(fn, object))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1>
QFuture<T> run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1) const, const Arg1 &arg1)
{
return (new typename SelectStoredConstMemberFunctionCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
QFuture<T> run(QThreadPool *pool, const Class &object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2)
{
return (new typename SelectStoredConstMemberFunctionCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
template <typename T, typename Class>
QFuture<T> run(QThreadPool *pool, Class *object, T (Class::*fn)())
{
return (new typename SelectStoredMemberFunctionPointerCall0<T, Class>::type(fn, object))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1>
QFuture<T> run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1), const Arg1 &arg1)
{
return (new typename SelectStoredMemberFunctionPointerCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
QFuture<T> run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1, Param2), const Arg1 &arg1, const Arg2 &arg2)
{
return (new typename SelectStoredMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
QFuture<T> run(QThreadPool *pool, Class *object, T (Class::*fn)(Param1, Param2, Param3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
{
return (new typename SelectStoredMemberFunctionPointerCall3<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
template <typename T, typename Class>
QFuture<T> run(QThreadPool *pool, const Class *object, T (Class::*fn)() const)
{
return (new typename SelectStoredConstMemberFunctionPointerCall0<T, Class>::type(fn, object))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1>
QFuture<T> run(QThreadPool *pool, const Class *object, T (Class::*fn)(Param1) const, const Arg1 &arg1)
{
return (new typename SelectStoredConstMemberFunctionPointerCall1<T, Class, Param1, Arg1>::type(fn, object, arg1))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2>
QFuture<T> run(QThreadPool *pool, const Class *object, T (Class::*fn)(Param1, Param2) const, const Arg1 &arg1, const Arg2 &arg2)
{
return (new typename SelectStoredConstMemberFunctionPointerCall2<T, Class, Param1, Arg1, Param2, Arg2>::type(fn, object, arg1, arg2))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3>::type(fn, object, arg1, arg2, arg3))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4>::type(fn, object, arg1, arg2, arg3, arg4))->start(pool);
}
template <typename T, typename Class, typename Param1, typename Arg1, typename Param2, typename Arg2, typename Param3, typename Arg3, typename Param4, typename Arg4, typename Param5, typename Arg5>
QFuture<T> 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<T, Class, Param1, Arg1, Param2, Arg2, Param3, Arg3, Param4, Arg4, Param5, Arg5>::type(fn, object, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
} //namespace QtConcurrent } //namespace QtConcurrent
#endif // Q_QDOC #endif // Q_QDOC

View File

@ -77,10 +77,16 @@ class RunFunctionTaskBase : public QFutureInterface<T> , public QRunnable
public: public:
QFuture<T> start() QFuture<T> start()
{ {
return start(QThreadPool::globalInstance());
}
QFuture<T> start(QThreadPool *pool)
{
this->setThreadPool(pool);
this->setRunnable(this); this->setRunnable(this);
this->reportStarted(); this->reportStarted();
QFuture<T> theFuture = this->future(); QFuture<T> theFuture = this->future();
QThreadPool::globalInstance()->start(this, /*m_priority*/ 0); pool->start(this, /*m_priority*/ 0);
return theFuture; return theFuture;
} }

View File

@ -95,8 +95,9 @@ void tst_QtConcurrentRun::runLightFunction()
void tst_QtConcurrentRun::runHeavyFunction() void tst_QtConcurrentRun::runHeavyFunction()
{ {
QThreadPool pool;
qDebug("starting function"); qDebug("starting function");
QFuture<void> future = run(heavy); QFuture<void> future = run(&pool, heavy);
qDebug("waiting"); qDebug("waiting");
future.waitForFinished(); future.waitForFinished();
qDebug("done"); qDebug("done");
@ -136,60 +137,95 @@ public:
void tst_QtConcurrentRun::returnValue() void tst_QtConcurrentRun::returnValue()
{ {
QThreadPool pool;
QFuture<int> f; QFuture<int> f;
f = run(returnInt0); f = run(returnInt0);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, returnInt0);
QCOMPARE(f.result(), 10);
A a; A a;
f = run(&a, &A::member0); f = run(&a, &A::member0);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, &a, &A::member0);
QCOMPARE(f.result(), 10);
f = run(&a, &A::member1, 20); f = run(&a, &A::member1, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, &a, &A::member1, 20);
QCOMPARE(f.result(), 20);
f = run(a, &A::member0); f = run(a, &A::member0);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, a, &A::member0);
QCOMPARE(f.result(), 10);
f = run(a, &A::member1, 20); f = run(a, &A::member1, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, a, &A::member1, 20);
QCOMPARE(f.result(), 20);
f = run(a); f = run(a);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, a);
QCOMPARE(f.result(), 10);
f = run(&a); f = run(&a);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, &a);
QCOMPARE(f.result(), 10);
f = run(a, 20); f = run(a, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, a, 20);
QCOMPARE(f.result(), 20);
f = run(&a, 20); f = run(&a, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, &a, 20);
QCOMPARE(f.result(), 20);
const AConst aConst = AConst(); const AConst aConst = AConst();
f = run(&aConst, &AConst::member0); f = run(&aConst, &AConst::member0);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, &aConst, &AConst::member0);
QCOMPARE(f.result(), 10);
f = run(&aConst, &AConst::member1, 20); f = run(&aConst, &AConst::member1, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, &aConst, &AConst::member1, 20);
QCOMPARE(f.result(), 20);
f = run(aConst, &AConst::member0); f = run(aConst, &AConst::member0);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, aConst, &AConst::member0);
QCOMPARE(f.result(), 10);
f = run(aConst, &AConst::member1, 20); f = run(aConst, &AConst::member1, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, aConst, &AConst::member1, 20);
QCOMPARE(f.result(), 20);
f = run(aConst); f = run(aConst);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, aConst);
QCOMPARE(f.result(), 10);
f = run(&aConst); f = run(&aConst);
QCOMPARE(f.result(), 10); QCOMPARE(f.result(), 10);
f = run(&pool, &aConst);
QCOMPARE(f.result(), 10);
f = run(aConst, 20); f = run(aConst, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, aConst, 20);
QCOMPARE(f.result(), 20);
f = run(&aConst, 20); f = run(&aConst, 20);
QCOMPARE(f.result(), 20); QCOMPARE(f.result(), 20);
f = run(&pool, &aConst, 20);
QCOMPARE(f.result(), 20);
} }
struct TestClass struct TestClass
@ -212,6 +248,7 @@ struct TestConstClass
void tst_QtConcurrentRun::functionObject() void tst_QtConcurrentRun::functionObject()
{ {
QThreadPool pool;
QFuture<void> f; QFuture<void> f;
TestClass c; TestClass c;
@ -220,16 +257,28 @@ void tst_QtConcurrentRun::functionObject()
f = run(c, 10); f = run(c, 10);
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(); const TestConstClass cc = TestConstClass();
f = run(cc); f = run(cc);
f = run(&cc); f = run(&cc);
f = run(cc, 10); f = run(cc, 10);
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() void tst_QtConcurrentRun::memberFunctions()
{ {
QThreadPool pool;
TestClass c; TestClass c;
run(c, &TestClass::foo).waitForFinished(); 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(&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(); const TestConstClass cc = TestConstClass();
run(cc, &TestConstClass::foo).waitForFinished(); run(cc, &TestConstClass::foo).waitForFinished();
run(&cc, &TestConstClass::foo).waitForFinished(); run(&cc, &TestConstClass::foo).waitForFinished();
run(cc, &TestConstClass::fooInt, 10).waitForFinished(); run(cc, &TestConstClass::fooInt, 10).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() void tst_QtConcurrentRun::implicitConvertibleTypes()
{ {
QThreadPool pool;
double d; double d;
run(doubleFunction, d).waitForFinished(); run(doubleFunction, d).waitForFinished();
run(&pool, doubleFunction, d).waitForFinished();
int i; int i;
run(doubleFunction, d).waitForFinished(); run(doubleFunction, d).waitForFinished();
run(&pool, doubleFunction, d).waitForFinished();
run(doubleFunction, i).waitForFinished(); run(doubleFunction, i).waitForFinished();
run(&pool, doubleFunction, i).waitForFinished();
run(doubleFunction, 10).waitForFinished(); run(doubleFunction, 10).waitForFinished();
run(&pool, doubleFunction, 10).waitForFinished();
run(stringFunction, QLatin1String("Foo")).waitForFinished(); run(stringFunction, QLatin1String("Foo")).waitForFinished();
run(&pool, stringFunction, QLatin1String("Foo")).waitForFinished();
run(stringConstRefFunction, QLatin1String("Foo")).waitForFinished(); run(stringConstRefFunction, QLatin1String("Foo")).waitForFinished();
run(&pool, stringConstRefFunction, QLatin1String("Foo")).waitForFinished();
QString string; QString string;
run(stringRefFunction, string).waitForFinished(); run(stringRefFunction, string).waitForFinished();
run(&pool, stringRefFunction, string).waitForFinished();
} }
void fn() { } void fn() { }
@ -382,7 +450,10 @@ int throwFunctionReturn()
void tst_QtConcurrentRun::exceptions() void tst_QtConcurrentRun::exceptions()
{ {
bool caught = false; QThreadPool pool;
bool caught;
caught = false;
try { try {
QtConcurrent::run(throwFunction).waitForFinished(); QtConcurrent::run(throwFunction).waitForFinished();
} catch (QException &) { } catch (QException &) {
@ -391,6 +462,15 @@ void tst_QtConcurrentRun::exceptions()
if (!caught) if (!caught)
QFAIL("did not get exception"); 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; caught = false;
try { try {
QtConcurrent::run(throwFunctionReturn).waitForFinished(); QtConcurrent::run(throwFunctionReturn).waitForFinished();
@ -399,6 +479,15 @@ void tst_QtConcurrentRun::exceptions()
} }
if (!caught) if (!caught)
QFAIL("did not get exception"); 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 #endif
@ -438,6 +527,27 @@ void tst_QtConcurrentRun::functor()
QtConcurrent::run(f, 1,2,3,4).waitForFinished(); QtConcurrent::run(f, 1,2,3,4).waitForFinished();
QtConcurrent::run(f, 1,2,3,4,5).waitForFinished(); QtConcurrent::run(f, 1,2,3,4,5).waitForFinished();
} }
// and now with explicit pool:
QThreadPool pool;
{
QFuture<int> fut = QtConcurrent::run(&pool, f);
QCOMPARE(fut.result(), 42);
}
{
QFuture<double> fut = QtConcurrent::run(&pool, f, 8.5, 1.8);
QCOMPARE(fut.result(), (8.5/1.8));
}
{
QFuture<int> 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 #endif
@ -458,6 +568,22 @@ void tst_QtConcurrentRun::lambda()
QCOMPARE(r, QStringList({"Hello", "World", "Foo"})); QCOMPARE(r, QStringList({"Hello", "World", "Foo"}));
} }
#endif #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<QStringList> f1 = QtConcurrent::run(&pool, [&](){ return str.split(' '); });
auto r = f1.result();
QCOMPARE(r, QStringList({"Hello", "World", "Foo"}));
}
#endif
} }
#endif #endif