6#error Do not include qfuture_impl.h directly
10#pragma qt_sync_skip_header_check
11#pragma qt_sync_stop_processing
14#include <QtCore/qglobal.h>
15#include <QtCore/qfunctionaltools_impl.h>
16#include <QtCore/qfutureinterface.h>
17#include <QtCore/qthreadpool.h>
18#include <QtCore/qexception.h>
19#include <QtCore/qpromise.h>
20#include <QtCore/qvariant.h>
63template<
typename F,
typename Arg,
typename Enable =
void>
69template<
typename F,
typename Arg>
77template<
class F,
class Arg>
102template<
class T,
class Enable =
void>
111template<
class Tuple,
std::size_t... I>
114 return std::make_tuple(
std::get<I>(t)...);
117template<
class Arg,
class... Args>
120 using TupleType = std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>;
121 constexpr auto Size =
sizeof...(Args);
122 if constexpr (QtPrivate::IsPrivateSignalArg<std::tuple_element_t<Size, TupleType>>) {
123 if constexpr (Size == 1) {
124 return std::forward<Arg>(arg);
126 return cutTuple(std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...),
127 std::make_index_sequence<Size>());
130 return std::make_tuple(
std::forward<Arg>(arg),
std::forward<Args>(args)...);
136template<
class Arg,
class...
Args>
145template<
typename Arg,
typename... Args>
158template<
typename Arg,
typename... Args>
194template<
typename R,
typename... Args>
199template<
typename R,
typename... Args>
204template<
typename R,
typename... Args>
209template<
typename R,
typename... Args>
214template<
typename R,
typename... Args>
219template<
typename Class,
typename R,
typename... Args>
224template<
typename Class,
typename R,
typename... Args>
229template<
typename Class,
typename R,
typename... Args>
234template<
typename Class,
typename R,
typename... Args>
239template<
typename Class,
typename R,
typename... Args>
244template<
typename Class,
typename R,
typename... Args>
273template<
class...
Args>
288template<
class Iterator>
291 std::forward_iterator_tag>;
293template<
typename Function,
typename ResultType,
typename ParentResultType>
300 template<
typename F = Function>
306 template<
typename F = Function>
312 runObj = QRunnable::create([continuation =
this] {
313 continuation->runFunction();
316 runObj->setAutoDelete(
false);
325 template<
typename F = Function>
329 template<
typename F = Function>
333 template<
typename F = Function>
338 void fulfillPromiseWithResult();
339 void fulfillVoidPromise();
340 void fulfillPromiseWithVoidResult();
342 template<
class... Args>
343 void fulfillPromise(Args &&... args);
352 QThreadPool *pool = threadPool ? threadPool : QThreadPool::globalInstance();
372#ifndef QT_NO_EXCEPTIONS
374template<
class Function,
class ResultType>
378 template<
typename F = Function>
379 static void create(F &&function, QFuture<ResultType> *future,
382 template<
typename F = Function>
386 template<
typename F = Function>
396 template<
class ArgType>
397 void handleException();
398 void handleAllExceptions();
402 QFuture<ResultType> parentFuture;
408template<
typename Function,
typename ResultType,
typename ParentResultType>
413 Q_ASSERT(parentFuture.isFinished());
415#ifndef QT_NO_EXCEPTIONS
418 if constexpr (!
std::is_void_v<ResultType>) {
419 if constexpr (
std::is_void_v<ParentResultType>) {
420 fulfillPromiseWithVoidResult();
421 }
else if constexpr (
std::is_invocable_v<Function, ParentResultType>) {
422 fulfillPromiseWithResult();
426 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
427 "The continuation is not invocable with the provided arguments");
428 fulfillPromise(parentFuture);
431 if constexpr (
std::is_void_v<ParentResultType>) {
432 if constexpr (std::is_invocable_v<Function, QFuture<
void>>)
433 this->object()(parentFuture);
436 }
else if constexpr (
std::is_invocable_v<Function, ParentResultType>) {
437 fulfillVoidPromise();
441 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
442 "The continuation is not invocable with the provided arguments");
443 this->object()(parentFuture);
446#ifndef QT_NO_EXCEPTIONS
448 promise.setException(
std::current_exception());
454template<
typename Function,
typename ResultType,
typename ParentResultType>
457 Q_ASSERT(parentFuture.isFinished());
459 if (parentFuture.d.isChainCanceled()) {
460#ifndef QT_NO_EXCEPTIONS
461 if (parentFuture.d.hasException()) {
466 if constexpr (!std::is_invocable_v<std::decay_t<Function>, QFuture<ParentResultType>>) {
468 promise.setException(parentFuture.d.exceptionStore().exception());
487template<
class Function>
494 Q_ASSERT_X(
false,
"QFuture",
"Continuation shouldn't be copied");
499 template <
typename F = Function,
500 std::enable_if_t<std::is_invocable_v<F,
const QFutureInterfaceBase &>,
bool> =
true>
501 void operator()(
const QFutureInterfaceBase &parentData) { function(parentData); }
503 template <
typename F = Function, std::enable_if_t<std::is_invocable_v<F>,
bool> =
true>
513 QFuture<ParentResultType> *f,
519 QThreadPool *pool =
nullptr;
523 launchAsync = f->d.launchAsync();
526 if (launchAsync && f->d.threadPool()) {
527 pool = f->d.threadPool();
528 fi.setThreadPool(pool);
532 fi.setLaunchAsync(launchAsync);
534 auto continuation = [func = std::forward<F>(func), fi, promise_ = QPromise(fi), pool,
535 launchAsync](
const QFutureInterfaceBase &parentData)
mutable {
536 const auto parent =
QFutureInterface<ParentResultType>(parentData).future();
540 std::forward<Function>(func), parent,
std::move(promise_), pool);
541 fi.setRunnable(asyncJob->runnable());
542 continuationJob = asyncJob;
545 std::forward<Function>(func), parent,
std::move(promise_));
552 if (!(launchAsync && isLaunched)) {
553 delete continuationJob;
554 continuationJob =
nullptr;
557 f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d,
558 QFutureInterfaceBase::ContinuationType::Then);
564 QFuture<ParentResultType> *f,
570 fi.setLaunchAsync(
true);
571 fi.setThreadPool(pool);
573 auto continuation = [func = std::forward<F>(func), promise_ =
QPromise(fi),
574 pool](
const QFutureInterfaceBase &parentData)
mutable {
575 const auto parent =
QFutureInterface<ParentResultType>(parentData).future();
577 std::forward<Function>(func), parent,
std::move(promise_), pool);
578 bool isLaunched = continuationJob->execute();
582 delete continuationJob;
583 continuationJob =
nullptr;
586 f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d,
587 QFutureInterfaceBase::ContinuationType::Then);
593 QFuture<ParentResultType> *f,
603 auto continuation = [func = std::forward<F>(func), parent = *f,
604 promise_ =
QPromise(fi)]()
mutable {
606 std::forward<Function>(func), parent, std::move(promise_));
610 f->d.setContinuation(context, ContinuationWrapper(std::move(continuation)),
611 QVariant::fromValue(fi),
612 QFutureInterfaceBase::ContinuationType::Then);
615template<
typename Function,
typename ResultType,
typename ParentResultType>
616void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromiseWithResult()
618 qfutureWarnIfUnusedResults(parentFuture.resultCount());
619 if constexpr (std::is_copy_constructible_v<ParentResultType>)
620 fulfillPromise(parentFuture.result());
622 fulfillPromise(parentFuture.takeResult());
625template<
typename Function,
typename ResultType,
typename ParentResultType>
628 qfutureWarnIfUnusedResults(parentFuture.resultCount());
629 if constexpr (std::is_copy_constructible_v<ParentResultType>)
630 this->object()(parentFuture.result());
632 this->object()(parentFuture.takeResult());
635template<
typename Function,
typename ResultType,
typename ParentResultType>
636void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromiseWithVoidResult()
638 if constexpr (std::is_invocable_v<Function, QFuture<
void>>)
639 fulfillPromise(parentFuture);
645template<
class... Args>
646void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromise(Args &&... args)
648 promise.addResult(std::invoke(
this->object(), std::forward<Args>(args)...));
654 if constexpr (!
std::is_void_v<T>) {
655 if constexpr (
std::is_copy_constructible_v<T>)
656 promise.addResult(future.result());
658 promise.addResult(future.takeResult());
662template<
class T,
class Function>
665 if constexpr (
std::is_void_v<T>)
668 promise.addResult(handler());
671#ifndef QT_NO_EXCEPTIONS
675void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
680 auto failureContinuation = [function = std::forward<F>(function), promise_ =
QPromise(fi)](
681 const QFutureInterfaceBase &parentData)
mutable {
683 FailureHandler<Function, ResultType> failureHandler(
std::forward<Function>(function),
684 parent,
std::move(promise_));
688 future->d.setContinuation(ContinuationWrapper(std::move(failureContinuation)), fi.d,
689 QFutureInterfaceBase::ContinuationType::OnFailed);
694void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
700 auto failureContinuation = [function = std::forward<F>(function),
701 parent = *future, promise_ =
QPromise(fi)]()
mutable {
703 std::forward<Function>(function), parent, std::move(promise_));
707 future->d.setContinuation(context, ContinuationWrapper(std::move(failureContinuation)),
708 QVariant::fromValue(fi),
709 QFutureInterfaceBase::ContinuationType::OnFailed);
712template<
class Function,
class ResultType>
715 Q_ASSERT(parentFuture.isFinished());
719 if (parentFuture.d.hasException()) {
721 if constexpr (
std::is_void_v<ArgType>) {
722 handleAllExceptions();
724 handleException<ArgType>();
726 }
else if (parentFuture.d.isChainCanceled()) {
727 promise.future().cancel();
729 QtPrivate::fulfillPromise(promise, parentFuture);
735template<
class ArgType>
739 Q_ASSERT(parentFuture.d.hasException());
740 parentFuture.d.exceptionStore().rethrowException();
741 }
catch (
const ArgType &e) {
744 if constexpr (
std::is_void_v<ResultType>)
747 promise.addResult(handler(e));
749 promise.setException(
std::current_exception());
754 promise.setException(
std::current_exception());
758template<
class Function,
class ResultType>
762 Q_ASSERT(parentFuture.d.hasException());
763 parentFuture.d.exceptionStore().rethrowException();
766 QtPrivate::fulfillPromise(promise,
std::forward<Function>(handler));
768 promise.setException(
std::current_exception());
775template<
class Function,
class ResultType>
779 template<
class F = Function>
784 auto canceledContinuation = [promise = QPromise(fi), handler =
std::forward<F>(handler)](
785 const QFutureInterfaceBase &parentData)
mutable {
787 run(
std::forward<F>(handler), parentFuture,
std::move(promise));
789 future->d.setContinuation(ContinuationWrapper(std::move(canceledContinuation)), fi.d,
790 QFutureInterfaceBase::ContinuationType::OnCanceled);
793 template<
class F = Function>
799 auto canceledContinuation = [handler = std::forward<F>(handler),
800 parentFuture = *future, promise =
QPromise(fi)]()
mutable {
801 run(std::forward<F>(handler), parentFuture, std::move(promise));
804 future->d.setContinuation(context, ContinuationWrapper(std::move(canceledContinuation)),
805 QVariant::fromValue(fi),
806 QFutureInterfaceBase::ContinuationType::OnCanceled);
809 template<
class F = Function>
810 static void run(F &&handler, QFuture<ResultType> &parentFuture,
QPromise<ResultType> &&promise)
814 if (parentFuture.isCanceled()) {
815#ifndef QT_NO_EXCEPTIONS
816 if (parentFuture.d.hasException()) {
818 promise.setException(parentFuture.d.exceptionStore().exception());
822 QtPrivate::fulfillPromise(promise,
std::forward<F>(handler));
823#ifndef QT_NO_EXCEPTIONS
825 promise.setException(
std::current_exception());
830 QtPrivate::fulfillPromise(promise, parentFuture);
844 using ResultType =
typename QtPrivate::Future<std::decay_t<T>>::type;
845 using NestedType =
typename QtPrivate::Future<ResultType>::type;
846 QFutureInterface<NestedType> promise(QFutureInterfaceBase::State::Pending);
848 outer->then([promise](
const QFuture<ResultType> &outerFuture)
mutable {
852 Q_ASSERT(outerFuture.isFinished());
853#ifndef QT_NO_EXCEPTIONS
854 if (outerFuture.d.hasException()) {
855 promise.reportStarted();
856 promise.reportException(outerFuture.d.exceptionStore().exception());
857 promise.reportFinished();
862 promise.reportStarted();
863 ResultType nestedFuture = outerFuture.result();
865 nestedFuture.then([promise] (
const QFuture<NestedType> &nested)
mutable {
866#ifndef QT_NO_EXCEPTIONS
867 if (nested.d.hasException()) {
868 promise.reportException(nested.d.exceptionStore().exception());
872 if constexpr (!std::is_void_v<NestedType>)
873 promise.reportResults(nested.results());
875 promise.reportFinished();
876 }).onCanceled([promise] ()
mutable {
877 promise.reportCanceled();
878 promise.reportFinished();
880 }).onCanceled([promise]()
mutable {
882 promise.reportStarted();
883 promise.reportCanceled();
884 promise.reportFinished();
886 return promise.future();
890template<
typename ValueType>
894 promise.reportStarted();
895 promise.reportResults(values);
896 promise.reportFinished();
897 return promise.future();
904template<
class Signal>
910 using ArgsType = ArgsType<Signal>;
911 QFutureInterface<ArgsType> promise;
912 promise.reportStarted();
914 promise.reportCanceled();
915 promise.reportFinished();
916 return promise.future();
919 using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
920 auto connections = std::make_shared<Connections>();
922 if constexpr (std::is_void_v<ArgsType>) {
924 QObject::connect(sender, signal, sender, [promise, connections]()
mutable {
925 QObject::disconnect(connections->first);
926 QObject::disconnect(connections->second);
927 promise.reportFinished();
930 connections->first = QObject::connect(sender, signal, sender,
931 [promise, connections](
auto... values)
mutable {
932 QObject::disconnect(connections->first);
933 QObject::disconnect(connections->second);
934 promise.reportResult(QtPrivate::createTuple(
935 std::move(values)...));
936 promise.reportFinished();
939 connections->first = QObject::connect(sender, signal, sender,
940 [promise, connections](ArgsType value)
mutable {
941 QObject::disconnect(connections->first);
942 QObject::disconnect(connections->second);
943 promise.reportResult(value);
944 promise.reportFinished();
948 if (!connections->first) {
949 promise.reportCanceled();
950 promise.reportFinished();
951 return promise.future();
954 connections->second =
955 QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]()
mutable {
956 QObject::disconnect(connections->first);
957 QObject::disconnect(connections->second);
958 promise.reportCanceled();
959 promise.reportFinished();
962 return promise.future();
974template<
typename Container, if_container_with_input_iterators<Container> =
true>
979 using ValueType = ContainedType<Container>;
980 if constexpr (std::is_convertible_v<q20::remove_cvref_t<Container>, QList<ValueType>>) {
981 return QtPrivate::makeReadyRangeFutureImpl(container);
983 return QtPrivate::makeReadyRangeFutureImpl(QList<ValueType>{std::cbegin(container),
984 std::cend(container)});
997 QFutureInterface<std::decay_t<T>> promise;
998 promise.reportStarted();
999 promise.reportResult(
std::forward<T>(value));
1000 promise.reportFinished();
1002 return promise.future();
1007#if QT_DEPRECATED_SINCE(6
, 10
)
1026#ifndef QT_NO_EXCEPTIONS
1028template<
typename T =
void>
1032 promise.reportStarted();
1033 promise.reportException(exception);
1034 promise.reportFinished();
1036 return promise.future();
1039template<
typename T =
void>
1045 return makeExceptionalFuture<T>(
std::current_exception());
1056template<
typename ResultFutures>
1067 const auto oldRemaining = remaining.fetchAndSubRelaxed(1);
1068 Q_ASSERT(oldRemaining > 0);
1069 if (oldRemaining <= 1) {
1080template<
typename ResultType>
1088 if (!ready.fetchAndStoreRelaxed(
true)) {
1098template<qsizetype Index,
typename ContextType,
typename... Ts>
1100 const std::tuple<Ts...> &t)
1102 auto future =
std::get<Index>(t);
1103 using ResultType =
typename ContextType::ValueType;
1105 future.then([context=context](
const std::tuple_element_t<Index, std::tuple<Ts...>> &f) {
1106 context->checkForCompletion(Index, ResultType {
std::in_place_index<Index>, f });
1107 }).onCanceled([context=context, future]() {
1108 context->checkForCompletion(Index, ResultType {
std::in_place_index<Index>, future });
1111 if constexpr (Index != 0)
1112 addCompletionHandlersImpl<Index - 1, ContextType, Ts...>(context, t);
1115template<
typename ContextType,
typename... Ts>
1118 constexpr qsizetype size =
std::tuple_size<
std::tuple<Ts...>>::value;
1119 addCompletionHandlersImpl<size - 1, ContextType, Ts...>(context, t);
1147template<
typename OutputSequence,
typename... Futures>
1150 constexpr qsizetype size =
sizeof...(Futures);
1152 context->futures.resize(size);
1153 context->promise.start();
1155 QtPrivate::addCompletionHandlers(context,
std::make_tuple(
std::forward<Futures>(futures)...));
1157 return context->promise.future();
static void create(F &&handler, QFuture< ResultType > *future, QFutureInterface< ResultType > &fi, QObject *context)
static void create(F &&handler, QFuture< ResultType > *future, QFutureInterface< ResultType > &fi)
static void run(F &&handler, QFuture< ResultType > &parentFuture, QPromise< ResultType > &&promise)
static void create(F &&func, QFuture< ParentResultType > *f, QFutureInterface< ResultType > &fi, QtFuture::Launch policy)
QPromise< ResultType > promise
CompactContinuation(F &&func, const QFuture< ParentResultType > &f, QPromise< ResultType > &&p)
CompactContinuation(F &&func, const QFuture< ParentResultType > &f, QPromise< ResultType > &&p, QThreadPool *pool)
static void create(F &&func, QFuture< ParentResultType > *f, QFutureInterface< ResultType > &fi, QThreadPool *pool)
QFuture< ParentResultType > parentFuture
QRunnable * runnable() const
static void create(F &&function, QFuture< ResultType > *future, QFutureInterface< ResultType > &fi, QObject *context)
static void create(F &&function, QFuture< ResultType > *future, const QFutureInterface< ResultType > &fi)
FailureHandler(F &&func, const QFuture< ResultType > &f, QPromise< ResultType > &&p)
typename QtPrivate::ArgResolver< Signal >::AllArgs ArgsType
static QFuture< T > makeExceptionalFuture(const QException &exception)
static QFuture< std::decay_t< T > > makeReadyValueFuture(T &&value)
static QFuture< T > makeExceptionalFuture(std::exception_ptr exception)
WhenAnyResult(qsizetype, const QFuture< T > &) -> WhenAnyResult< T >
static QFuture< ContainedType< Container > > makeReadyRangeFuture(Container &&container)
static QFuture< ValueType > makeReadyRangeFuture(std::initializer_list< ValueType > values)
static QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
auto createTuple(Arg &&arg, Args &&... args)
void qfutureWarnIfUnusedResults(qsizetype numResults)
void addCompletionHandlersImpl(const std::shared_ptr< ContextType > &context, const std::tuple< Ts... > &t)
void fulfillPromise(QPromise< T > &promise, Function &&handler)
constexpr bool isQFutureV
QFuture< OutputSequence > whenAllImpl(Futures &&... futures)
void fulfillPromise(QPromise< T > &promise, QFuture< T > &future)
QFuture< ValueType > makeReadyRangeFutureImpl(const QList< ValueType > &values)
constexpr bool IsPrivateSignalArg
auto cutTuple(Tuple &&t, std::index_sequence< I... >)
std::is_convertible< typename std::iterator_traits< Iterator >::iterator_category, std::forward_iterator_tag > IsForwardIterable
void addCompletionHandlers(const std::shared_ptr< ContextType > &context, const std::tuple< Ts... > &t)
static const bool CanInvokeWithArgs
static const bool HasExtraArgs
static const bool HasExtraArgs
static const bool CanInvokeWithArgs
static const bool HasExtraArgs
static const bool CanInvokeWithArgs
ContinuationWrapper(ContinuationWrapper &&other)=default
ContinuationWrapper & operator=(ContinuationWrapper &&)=default
void operator()(const QFutureInterfaceBase &parentData)
ContinuationWrapper(Function &&f)
ContinuationWrapper(const ContinuationWrapper &other)
static auto unwrapImpl(T *outer)
QAtomicInteger< qsizetype > remaining
QPromise< ResultFutures > promise
WhenAllContext(qsizetype size)
void checkForCompletion(qsizetype index, T &&future)
typename ResultFutures::value_type ValueType
QPromise< ResultType > promise
void checkForCompletion(qsizetype, T &&result)