Create any callable using QRunnable::create
The overhead of making new custom classes appears to be less than constructing a generic std::function. [ChangeLog][QtCore][QRunnable] QRunnable::create can now take non-copyable functions as argument. Task-number: QTBUG-112302 Change-Id: Ied870f13ca6c7eaa14ed6eff9c4e676c7b73881c Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
5c4a94ba85
commit
c080d1e64d
@ -509,6 +509,13 @@ QByteArray QMessageAuthenticationCode::hash(const QByteArray &msg, const QByteAr
|
|||||||
qToByteArrayViewIgnoringNull(key), method);
|
qToByteArrayViewIgnoringNull(key), method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "qrunnable.h"
|
||||||
|
|
||||||
|
QRunnable *QRunnable::create(std::function<void()> functionToRun)
|
||||||
|
{
|
||||||
|
return QRunnable::create<std::function<void()>>(std::move(functionToRun));
|
||||||
|
}
|
||||||
|
|
||||||
#include "qstring.h"
|
#include "qstring.h"
|
||||||
|
|
||||||
qsizetype QString::toUcs4_helper(const ushort *uc, qsizetype length, uint *out)
|
qsizetype QString::toUcs4_helper(const ushort *uc, qsizetype length, uint *out)
|
||||||
|
@ -77,31 +77,17 @@ QRunnable::~QRunnable()
|
|||||||
\sa autoDelete(), QThreadPool
|
\sa autoDelete(), QThreadPool
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class FunctionRunnable : public QRunnable
|
|
||||||
{
|
|
||||||
std::function<void()> m_functionToRun;
|
|
||||||
public:
|
|
||||||
FunctionRunnable(std::function<void()> functionToRun) : m_functionToRun(std::move(functionToRun))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void run() override
|
|
||||||
{
|
|
||||||
m_functionToRun();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
\fn template<typename Callable> QRunnable *QRunnable::create(Callable &&callableToRun);
|
||||||
\since 5.15
|
\since 5.15
|
||||||
|
|
||||||
Creates a QRunnable that calls \a functionToRun in run().
|
Creates a QRunnable that calls \a callableToRun in run().
|
||||||
|
|
||||||
Auto-deletion is enabled by default.
|
Auto-deletion is enabled by default.
|
||||||
|
|
||||||
|
\note In Qt versions prior to 6.6, this method took copyable functions only.
|
||||||
|
|
||||||
\sa run(), autoDelete()
|
\sa run(), autoDelete()
|
||||||
*/
|
*/
|
||||||
QRunnable *QRunnable::create(std::function<void()> functionToRun)
|
|
||||||
{
|
|
||||||
return new FunctionRunnable(std::move(functionToRun));
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2016 The Qt Company Ltd.
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
#ifndef QRUNNABLE_H
|
#ifndef QRUNNABLE_H
|
||||||
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -19,12 +20,70 @@ public:
|
|||||||
|
|
||||||
constexpr QRunnable() noexcept = default;
|
constexpr QRunnable() noexcept = default;
|
||||||
virtual ~QRunnable();
|
virtual ~QRunnable();
|
||||||
|
#if QT_CORE_REMOVED_SINCE(6, 6)
|
||||||
static QRunnable *create(std::function<void()> functionToRun);
|
static QRunnable *create(std::function<void()> functionToRun);
|
||||||
|
#endif
|
||||||
|
template <typename Callable>
|
||||||
|
static QRunnable *create(Callable &&functionToRun);
|
||||||
bool autoDelete() const { return m_autoDelete; }
|
bool autoDelete() const { return m_autoDelete; }
|
||||||
void setAutoDelete(bool autoDelete) { m_autoDelete = autoDelete; }
|
void setAutoDelete(bool autoDelete) { m_autoDelete = autoDelete; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Type erasure, to only instantiate a non-virtual class per Callable:
|
||||||
|
class QGenericRunnableHelperBase
|
||||||
|
{
|
||||||
|
using OpFn = void(*)(const QGenericRunnableHelperBase *);
|
||||||
|
OpFn runFn;
|
||||||
|
OpFn destroyFn;
|
||||||
|
protected:
|
||||||
|
constexpr explicit QGenericRunnableHelperBase(OpFn fn, OpFn del) noexcept : runFn(fn), destroyFn(del) {}
|
||||||
|
~QGenericRunnableHelperBase() = default;
|
||||||
|
public:
|
||||||
|
void run() { runFn(this); }
|
||||||
|
void destroy() { destroyFn(this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Callable>
|
||||||
|
class QGenericRunnableHelper : public QGenericRunnableHelperBase
|
||||||
|
{
|
||||||
|
Callable m_functionToRun;
|
||||||
|
public:
|
||||||
|
template <typename UniCallable>
|
||||||
|
QGenericRunnableHelper(UniCallable &&functionToRun) noexcept :
|
||||||
|
QGenericRunnableHelperBase(
|
||||||
|
[](const QGenericRunnableHelperBase *that) { static_cast<const QGenericRunnableHelper*>(that)->m_functionToRun(); },
|
||||||
|
[](const QGenericRunnableHelperBase *that) { delete static_cast<const QGenericRunnableHelper*>(that); }),
|
||||||
|
m_functionToRun(std::forward<UniCallable>(functionToRun))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QGenericRunnable : public QRunnable
|
||||||
|
{
|
||||||
|
QGenericRunnableHelperBase *runHelper;
|
||||||
|
public:
|
||||||
|
QGenericRunnable(QGenericRunnableHelperBase *runner) noexcept: runHelper(runner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~QGenericRunnable() override
|
||||||
|
{
|
||||||
|
runHelper->destroy();
|
||||||
|
}
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
runHelper->run();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Callable>
|
||||||
|
QRunnable *QRunnable::create(Callable &&functionToRun)
|
||||||
|
{
|
||||||
|
return new QGenericRunnable(
|
||||||
|
new QGenericRunnableHelper<std::decay_t<Callable>>(
|
||||||
|
std::forward<Callable>(functionToRun)));
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <QSemaphore>
|
#include <QSemaphore>
|
||||||
|
|
||||||
#include <qelapsedtimer.h>
|
#include <qelapsedtimer.h>
|
||||||
|
#include <qrunnable.h>
|
||||||
#include <qthreadpool.h>
|
#include <qthreadpool.h>
|
||||||
#include <qstring.h>
|
#include <qstring.h>
|
||||||
#include <qmutex.h>
|
#include <qmutex.h>
|
||||||
@ -45,6 +46,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void runFunction();
|
void runFunction();
|
||||||
void runFunction2();
|
void runFunction2();
|
||||||
|
void runFunction3();
|
||||||
void createThreadRunFunction();
|
void createThreadRunFunction();
|
||||||
void runMultiple();
|
void runMultiple();
|
||||||
void waitcomplete();
|
void waitcomplete();
|
||||||
@ -173,6 +175,23 @@ void tst_QThreadPool::runFunction2()
|
|||||||
QCOMPARE(localCount, 1);
|
QCOMPARE(localCount, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DeleteCheck
|
||||||
|
{
|
||||||
|
static bool s_deleted;
|
||||||
|
~DeleteCheck() { s_deleted = true; }
|
||||||
|
};
|
||||||
|
bool DeleteCheck::s_deleted = false;
|
||||||
|
|
||||||
|
void tst_QThreadPool::runFunction3()
|
||||||
|
{
|
||||||
|
std::unique_ptr<DeleteCheck> ptr(new DeleteCheck);
|
||||||
|
{
|
||||||
|
TestThreadPool manager;
|
||||||
|
manager.start(QRunnable::create([my_ptr = std::move(ptr)]() { }));
|
||||||
|
}
|
||||||
|
QVERIFY(DeleteCheck::s_deleted);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QThreadPool::createThreadRunFunction()
|
void tst_QThreadPool::createThreadRunFunction()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user