Add a constructor for QRunnable from anonymous functions

This makes it easier to create one without having to create
a derivative class. The patch also adds a path to avoid using
QRunnable directly in QThreadPool.

Change-Id: I9caa7dabb6f641b547d4771c863aa6ab7f01b704
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2019-11-21 15:51:34 +01:00
parent 6c4e0f2d2d
commit c76dd72dc6
5 changed files with 83 additions and 6 deletions

View File

@ -114,4 +114,31 @@ QRunnable::~QRunnable()
\sa autoDelete(), QThreadPool
*/
class FunctionRunnable : public QRunnable
{
std::function<void()> m_functor;
public:
FunctionRunnable(std::function<void()> functor) : m_functor(std::move(functor))
{
}
void run() override
{
m_functor();
}
};
/*!
\since 5.15
Creates a QRunnable that calls \a fun in run().
Auto-deletion is enabled by default.
\sa run(), autoDelete()
*/
QRunnable *QRunnable::create(std::function<void()> fun)
{
return new FunctionRunnable(std::move(fun));
}
QT_END_NAMESPACE

View File

@ -41,6 +41,7 @@
#define QRUNNABLE_H
#include <QtCore/qglobal.h>
#include <functional>
QT_BEGIN_NAMESPACE
@ -59,6 +60,7 @@ public:
QRunnable() : ref(0) { }
virtual ~QRunnable();
static QRunnable *create(std::function<void()> fun);
bool autoDelete() const { return ref != -1; }
void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; }

View File

@ -511,6 +511,22 @@ void QThreadPool::start(QRunnable *runnable, int priority)
}
}
/*!
\overload
\since 5.15
Reserves a thread and uses it to run \a fun, unless this thread will
make the current thread count exceed maxThreadCount(). In that case,
\a fun is added to a run queue instead. The \a priority argument can
be used to control the run queue's order of execution.
*/
void QThreadPool::start(std::function<void()> fun, int priority)
{
if (!fun)
return;
start(QRunnable::create(std::move(fun)), priority);
}
/*!
Attempts to reserve a thread to run \a runnable.
@ -542,6 +558,22 @@ bool QThreadPool::tryStart(QRunnable *runnable)
return d->tryStart(runnable);
}
/*!
\overload
\since 5.15
Attempts to reserve a thread to run \a fun.
If no threads are available at the time of calling, then this function
does nothing and returns \c false. Otherwise, \a fun is run immediately
using one available thread and this function returns \c true.
*/
bool QThreadPool::tryStart(std::function<void()> fun)
{
if (!fun)
return false;
return tryStart(QRunnable::create(std::move(fun)));
}
/*! \property QThreadPool::expiryTimeout
Threads that are unused for \a expiryTimeout milliseconds are considered

View File

@ -45,6 +45,8 @@
#include <QtCore/qthread.h>
#include <QtCore/qrunnable.h>
#include <functional>
QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
@ -70,6 +72,9 @@ public:
void start(QRunnable *runnable, int priority = 0);
bool tryStart(QRunnable *runnable);
void start(std::function<void()> fun, int priority = 0);
bool tryStart(std::function<void()> fun);
int expiryTimeout() const;
void setExpiryTimeout(int expiryTimeout);

View File

@ -64,6 +64,7 @@ public:
private slots:
void runFunction();
void runFunction2();
void createThreadRunFunction();
void runMultiple();
void waitcomplete();
@ -160,17 +161,27 @@ void tst_QThreadPool::runFunction()
{
QThreadPool manager;
testFunctionCount = 0;
manager.start(createTask(noSleepTestFunction));
manager.start(noSleepTestFunction);
}
QCOMPARE(testFunctionCount, 1);
}
void tst_QThreadPool::runFunction2()
{
int localCount = 0;
{
QThreadPool manager;
manager.start([&]() { ++localCount; });
}
QCOMPARE(localCount, 1);
}
void tst_QThreadPool::createThreadRunFunction()
{
{
QThreadPool manager;
testFunctionCount = 0;
manager.start(createTask(noSleepTestFunction));
manager.start(noSleepTestFunction);
}
QCOMPARE(testFunctionCount, 1);
@ -184,7 +195,7 @@ void tst_QThreadPool::runMultiple()
QThreadPool manager;
testFunctionCount = 0;
for (int i = 0; i < runs; ++i) {
manager.start(createTask(sleepTestFunctionMutex));
manager.start(sleepTestFunctionMutex);
}
}
QCOMPARE(testFunctionCount, runs);
@ -193,7 +204,7 @@ void tst_QThreadPool::runMultiple()
QThreadPool manager;
testFunctionCount = 0;
for (int i = 0; i < runs; ++i) {
manager.start(createTask(noSleepTestFunctionMutex));
manager.start(noSleepTestFunctionMutex);
}
}
QCOMPARE(testFunctionCount, runs);
@ -201,7 +212,7 @@ void tst_QThreadPool::runMultiple()
{
QThreadPool manager;
for (int i = 0; i < 500; ++i)
manager.start(createTask(emptyFunct));
manager.start(emptyFunct);
}
}
@ -211,7 +222,7 @@ void tst_QThreadPool::waitcomplete()
const int runs = 500;
for (int i = 0; i < 500; ++i) {
QThreadPool pool;
pool.start(createTask(noSleepTestFunction));
pool.start(noSleepTestFunction);
}
QCOMPARE(testFunctionCount, runs);
}