summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/thread/qfuture_impl.h37
-rw-r--r--src/corelib/thread/qfutureinterface.cpp32
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;