summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2023-03-28 10:38:25 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2023-04-04 01:05:47 +0200
commitc080d1e64d6e7c29bedfef48676f753c8bc0259c (patch)
tree801425a7e164e3eb62b370c592357bd37825c7d6 /src/corelib
parent5c4a94ba85f0bed9633c385455685ba364a72540 (diff)
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>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/compat/removed_api.cpp7
-rw-r--r--src/corelib/thread/qrunnable.cpp22
-rw-r--r--src/corelib/thread/qrunnable.h63
3 files changed, 72 insertions, 20 deletions
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp
index fdbe5de41c..e1d9c9eccf 100644
--- a/src/corelib/compat/removed_api.cpp
+++ b/src/corelib/compat/removed_api.cpp
@@ -509,6 +509,13 @@ QByteArray QMessageAuthenticationCode::hash(const QByteArray &msg, const QByteAr
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"
qsizetype QString::toUcs4_helper(const ushort *uc, qsizetype length, uint *out)
diff --git a/src/corelib/thread/qrunnable.cpp b/src/corelib/thread/qrunnable.cpp
index 5bb354cbb1..718802010a 100644
--- a/src/corelib/thread/qrunnable.cpp
+++ b/src/corelib/thread/qrunnable.cpp
@@ -77,31 +77,17 @@ QRunnable::~QRunnable()
\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
- Creates a QRunnable that calls \a functionToRun in run().
+ Creates a QRunnable that calls \a callableToRun in run().
Auto-deletion is enabled by default.
+ \note In Qt versions prior to 6.6, this method took copyable functions only.
+
\sa run(), autoDelete()
*/
-QRunnable *QRunnable::create(std::function<void()> functionToRun)
-{
- return new FunctionRunnable(std::move(functionToRun));
-}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qrunnable.h b/src/corelib/thread/qrunnable.h
index c77f8eea0a..131efdedb7 100644
--- a/src/corelib/thread/qrunnable.h
+++ b/src/corelib/thread/qrunnable.h
@@ -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
#ifndef QRUNNABLE_H
@@ -6,6 +6,7 @@
#include <QtCore/qglobal.h>
#include <functional>
+#include <type_traits>
QT_BEGIN_NAMESPACE
@@ -19,12 +20,70 @@ public:
constexpr QRunnable() noexcept = default;
virtual ~QRunnable();
+#if QT_CORE_REMOVED_SINCE(6, 6)
static QRunnable *create(std::function<void()> functionToRun);
-
+#endif
+ template <typename Callable>
+ static QRunnable *create(Callable &&functionToRun);
bool autoDelete() const { return m_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
#endif