diff options
-rw-r--r-- | src/corelib/thread/qfuture_impl.h | 37 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 32 |
2 files changed, 47 insertions, 22 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h index 5b4c929a36..d8fe946b92 100644 --- a/src/corelib/thread/qfuture_impl.h +++ b/src/corelib/thread/qfuture_impl.h @@ -590,6 +590,18 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func, f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d); } +// defined in qfutureinterface.cpp: +Q_CORE_EXPORT void watchContinuationImpl(const QObject *context, QSlotObjectBase *slotObj, + QFutureInterfaceBase &fi); +template <typename Continuation> +void watchContinuation(const QObject *context, Continuation &&c, QFutureInterfaceBase &fi) +{ + using Prototype = typename QtPrivate::Callable<Continuation>::Function; + watchContinuationImpl(context, + QtPrivate::makeCallableObject<Prototype>(std::forward<Continuation>(c)), + fi); +} + template<typename Function, typename ResultType, typename ParentResultType> template<typename F> void Continuation<Function, ResultType, ParentResultType>::create(F &&func, @@ -610,15 +622,7 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func, continuationJob.execute(); }; - auto *watcher = new QBasicFutureWatcher; - watcher->moveToThread(context->thread()); - QObject::connect(watcher, &QBasicFutureWatcher::finished, - context, std::move(continuation)); - QObject::connect(watcher, &QBasicFutureWatcher::finished, - watcher, &QObject::deleteLater); - QObject::connect(context, &QObject::destroyed, - watcher, &QObject::deleteLater); - watcher->setFuture(f->d); + QtPrivate::watchContinuation(context, std::move(continuation), f->d); } template<typename Function, typename ResultType, typename ParentResultType> @@ -710,12 +714,7 @@ void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultTy failureHandler.run(); }; - auto *watcher = new QBasicFutureWatcher; - watcher->moveToThread(context->thread()); - QObject::connect(watcher, &QBasicFutureWatcher::finished, context, std::move(failureContinuation)); - QObject::connect(watcher, &QBasicFutureWatcher::finished, watcher, &QObject::deleteLater); - QObject::connect(context, &QObject::destroyed, watcher, &QObject::deleteLater); - watcher->setFuture(future->d); + QtPrivate::watchContinuation(context, std::move(failureContinuation), future->d); } template<class Function, class ResultType> @@ -809,13 +808,7 @@ public: run(std::forward<F>(handler), parentFuture, std::move(promise)); }; - auto *watcher = new QBasicFutureWatcher; - watcher->moveToThread(context->thread()); - QObject::connect(watcher, &QBasicFutureWatcher::finished, - context, std::move(canceledContinuation)); - QObject::connect(watcher, &QBasicFutureWatcher::finished, watcher, &QObject::deleteLater); - QObject::connect(context, &QObject::destroyed, watcher, &QObject::deleteLater); - watcher->setFuture(future->d); + QtPrivate::watchContinuation(context, std::move(canceledContinuation), future->d); } template<class F = Function> diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index 8f73dde253..de936005c3 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -4,12 +4,14 @@ // qfutureinterface.h included from qfuture.h #include "qfuture.h" #include "qfutureinterface_p.h" +#include "qbasicfuturewatcher.h" #include <QtCore/qatomic.h> #include <QtCore/qthread.h> #include <QtCore/qvarlengtharray.h> #include <QtCore/private/qsimd_p.h> // for qYieldCpu() #include <private/qthreadpool_p.h> +#include <private/qobject_p.h> #ifdef interface # undef interface @@ -43,6 +45,36 @@ const auto suspendingOrSuspended = } // unnamed namespace +void QtPrivate::watchContinuationImpl(const QObject *context, QSlotObjectBase *slotObj, + QFutureInterfaceBase &fi) +{ + Q_ASSERT(context); + Q_ASSERT(slotObj); + + // ### we're missing `QSlotObjectPtr`... + struct Deleter { + void operator()(QSlotObjectBase *p) const { p->destroyIfLastRef(); } + }; + auto slot = std::unique_ptr<QSlotObjectBase, Deleter>(slotObj); + + auto *watcher = new QBasicFutureWatcher; + watcher->moveToThread(context->thread()); + // ### we're missing a convenient way to `QObject::connect()` to a `QSlotObjectBase`... + QObject::connect(watcher, &QBasicFutureWatcher::finished, + // for the following, cf. QMetaObject::invokeMethodImpl(): + // we know `slot` is a lambda returning `void`, so we can just + // `call()` with `obj` and `args[0]` set to `nullptr`: + watcher, [slot = std::move(slot)] { + void *args[] = { nullptr }; // for `void` return value + slot->call(nullptr, args); + }); + QObject::connect(watcher, &QBasicFutureWatcher::finished, + watcher, &QObject::deleteLater); + QObject::connect(context, &QObject::destroyed, + watcher, &QObject::deleteLater); + watcher->setFuture(fi); +} + QFutureCallOutInterface::~QFutureCallOutInterface() = default; |