5#error Do not include qfuture_impl.h directly
9#pragma qt_sync_skip_header_check
10#pragma qt_sync_stop_processing
13#include <QtCore/qglobal.h>
14#include <QtCore/qfunctionaltools_impl.h>
15#include <QtCore/qfutureinterface.h>
16#include <QtCore/qthreadpool.h>
17#include <QtCore/qexception.h>
18#include <QtCore/qpromise.h>
19#include <QtCore/qvariant.h>
59template<
typename F,
typename Arg,
typename Enable =
void>
65template<
typename F,
typename Arg>
73template<
class F,
class Arg>
98template<
class T,
class Enable =
void>
107template<
class Tuple,
std::size_t... I>
110 return std::make_tuple(
std::get<I>(t)...);
113template<
class Arg,
class... Args>
116 using TupleType = std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>;
117 constexpr auto Size =
sizeof...(Args);
118 if constexpr (QtPrivate::IsPrivateSignalArg<std::tuple_element_t<Size, TupleType>>) {
119 if constexpr (Size == 1) {
120 return std::forward<Arg>(arg);
122 return cutTuple(std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...),
123 std::make_index_sequence<Size>());
126 return std::make_tuple(
std::forward<Arg>(arg),
std::forward<Args>(args)...);
132template<
class Arg,
class...
Args>
141template<
typename Arg,
typename... Args>
142struct ArgsType<Arg, Args...>
145 using PromiseType =
void;
146 using IsPromise = std::false_type;
148 using AllArgs = FilterLastPrivateSignalArg<std::decay_t<Arg>, std::decay_t<Args>...>;
154template<
typename Arg,
typename... Args>
155struct ArgsType<QPromise<Arg> &, Args...>
157 using First = QPromise<Arg> &;
158 using PromiseType = Arg;
159 using IsPromise = std::true_type;
161 using AllArgs = FilterLastPrivateSignalArg<QPromise<Arg>, std::decay_t<Args>...>;
171 using PromiseType =
void;
172 using IsPromise = std::false_type;
174 using AllArgs =
void;
190template<
typename R,
typename... Args>
195template<
typename R,
typename... Args>
200template<
typename R,
typename... Args>
205template<
typename R,
typename... Args>
206struct ArgResolver<R (*
const)(Args...)> :
public ArgsType<Args...>
210template<
typename R,
typename... Args>
215template<
typename Class,
typename R,
typename... Args>
220template<
typename Class,
typename R,
typename... Args>
225template<
typename Class,
typename R,
typename... Args>
230template<
typename Class,
typename R,
typename... Args>
235template<
typename Class,
typename R,
typename... Args>
240template<
typename Class,
typename R,
typename... Args>
269template<
class...
Args>
284template<
class Iterator>
285using IsForwardIterable =
286 std::is_convertible<
typename std::iterator_traits<Iterator>::iterator_category,
287 std::forward_iterator_tag>;
289template<
typename Function,
typename ResultType,
typename ParentResultType>
296 template<
typename F = Function>
302 template<
typename F = Function>
308 runObj = QRunnable::create([continuation =
this] {
309 continuation->runFunction();
312 runObj->setAutoDelete(
false);
321 template<
typename F = Function>
325 template<
typename F = Function>
329 template<
typename F = Function>
334 void fulfillPromiseWithResult();
335 void fulfillVoidPromise();
336 void fulfillPromiseWithVoidResult();
338 template<
class... Args>
339 void fulfillPromise(Args &&... args);
348 QThreadPool *pool = threadPool ? threadPool : QThreadPool::globalInstance();
368#ifndef QT_NO_EXCEPTIONS
370template<
class Function,
class ResultType>
374 template<
typename F = Function>
375 static void create(F &&function, QFuture<ResultType> *future,
378 template<
typename F = Function>
382 template<
typename F = Function>
392 template<
class ArgType>
393 void handleException();
394 void handleAllExceptions();
397 QPromise<ResultType> promise;
398 QFuture<ResultType> parentFuture;
404template<
typename Function,
typename ResultType,
typename ParentResultType>
409 Q_ASSERT(parentFuture.isFinished());
411#ifndef QT_NO_EXCEPTIONS
414 if constexpr (!
std::is_void_v<ResultType>) {
415 if constexpr (
std::is_void_v<ParentResultType>) {
416 fulfillPromiseWithVoidResult();
417 }
else if constexpr (
std::is_invocable_v<Function, ParentResultType>) {
418 fulfillPromiseWithResult();
422 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
423 "The continuation is not invocable with the provided arguments");
424 fulfillPromise(parentFuture);
427 if constexpr (
std::is_void_v<ParentResultType>) {
428 if constexpr (std::is_invocable_v<Function, QFuture<
void>>)
429 this->object()(parentFuture);
432 }
else if constexpr (
std::is_invocable_v<Function, ParentResultType>) {
433 fulfillVoidPromise();
437 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
438 "The continuation is not invocable with the provided arguments");
439 this->object()(parentFuture);
442#ifndef QT_NO_EXCEPTIONS
444 promise.setException(
std::current_exception());
450template<
typename Function,
typename ResultType,
typename ParentResultType>
453 Q_ASSERT(parentFuture.isFinished());
455 if (parentFuture.d.isChainCanceled()) {
456#ifndef QT_NO_EXCEPTIONS
457 if (parentFuture.d.hasException()) {
462 if constexpr (!std::is_invocable_v<std::decay_t<Function>, QFuture<ParentResultType>>) {
464 promise.setException(parentFuture.d.exceptionStore().exception());
483template<
class Function>
490 Q_ASSERT_X(
false,
"QFuture",
"Continuation shouldn't be copied");
495 template <
typename F = Function,
496 std::enable_if_t<std::is_invocable_v<F,
const QFutureInterfaceBase &>,
bool> =
true>
497 void operator()(
const QFutureInterfaceBase &parentData) { function(parentData); }
499 template <
typename F = Function, std::enable_if_t<std::is_invocable_v<F>,
bool> =
true>
509 QFuture<ParentResultType> *f,
515 QThreadPool *pool =
nullptr;
519 launchAsync = f->d.launchAsync();
522 if (launchAsync && f->d.threadPool()) {
523 pool = f->d.threadPool();
524 fi.setThreadPool(pool);
528 fi.setLaunchAsync(launchAsync);
530 auto continuation = [func = std::forward<F>(func), fi, promise_ = QPromise(fi), pool,
531 launchAsync](
const QFutureInterfaceBase &parentData)
mutable {
532 const auto parent =
QFutureInterface<ParentResultType>(parentData).future();
536 std::forward<Function>(func), parent,
std::move(promise_), pool);
537 fi.setRunnable(asyncJob->runnable());
538 continuationJob = asyncJob;
541 std::forward<Function>(func), parent,
std::move(promise_));
548 if (!(launchAsync && isLaunched)) {
549 delete continuationJob;
550 continuationJob =
nullptr;
553 f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d,
554 QFutureInterfaceBase::ContinuationType::Then);
560 QFuture<ParentResultType> *f,
566 fi.setLaunchAsync(
true);
567 fi.setThreadPool(pool);
569 auto continuation = [func = std::forward<F>(func), promise_ = QPromise(fi),
570 pool](
const QFutureInterfaceBase &parentData)
mutable {
571 const auto parent =
QFutureInterface<ParentResultType>(parentData).future();
573 std::forward<Function>(func), parent,
std::move(promise_), pool);
574 bool isLaunched = continuationJob->execute();
578 delete continuationJob;
579 continuationJob =
nullptr;
582 f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d,
583 QFutureInterfaceBase::ContinuationType::Then);
589 QFuture<ParentResultType> *f,
599 auto continuation = [func = std::forward<F>(func), parent = *f,
600 promise_ = QPromise(fi)]()
mutable {
602 std::forward<Function>(func), parent, std::move(promise_));
606 f->d.setContinuation(context, ContinuationWrapper(std::move(continuation)),
607 QVariant::fromValue(fi),
608 QFutureInterfaceBase::ContinuationType::Then);
611template<
typename Function,
typename ResultType,
typename ParentResultType>
612void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromiseWithResult()
614 if constexpr (std::is_copy_constructible_v<ParentResultType>)
615 fulfillPromise(parentFuture.result());
617 fulfillPromise(parentFuture.takeResult());
620template<
typename Function,
typename ResultType,
typename ParentResultType>
623 if constexpr (std::is_copy_constructible_v<ParentResultType>)
624 this->object()(parentFuture.result());
626 this->object()(parentFuture.takeResult());
629template<
typename Function,
typename ResultType,
typename ParentResultType>
630void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromiseWithVoidResult()
632 if constexpr (std::is_invocable_v<Function, QFuture<
void>>)
633 fulfillPromise(parentFuture);
639template<
class... Args>
640void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromise(Args &&... args)
642 promise.addResult(std::invoke(
this->object(), std::forward<Args>(args)...));
648 if constexpr (!
std::is_void_v<T>) {
649 if constexpr (
std::is_copy_constructible_v<T>)
650 promise.addResult(future.result());
652 promise.addResult(future.takeResult());
656template<
class T,
class Function>
659 if constexpr (
std::is_void_v<T>)
662 promise.addResult(handler());
665#ifndef QT_NO_EXCEPTIONS
669void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
674 auto failureContinuation = [function = std::forward<F>(function), promise_ = QPromise(fi)](
675 const QFutureInterfaceBase &parentData)
mutable {
677 FailureHandler<Function, ResultType> failureHandler(
std::forward<Function>(function),
678 parent,
std::move(promise_));
682 future->d.setContinuation(ContinuationWrapper(std::move(failureContinuation)), fi.d,
683 QFutureInterfaceBase::ContinuationType::OnFailed);
688void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
694 auto failureContinuation = [function = std::forward<F>(function),
695 parent = *future, promise_ = QPromise(fi)]()
mutable {
697 std::forward<Function>(function), parent, std::move(promise_));
701 future->d.setContinuation(context, ContinuationWrapper(std::move(failureContinuation)),
702 QVariant::fromValue(fi),
703 QFutureInterfaceBase::ContinuationType::OnFailed);
706template<
class Function,
class ResultType>
709 Q_ASSERT(parentFuture.isFinished());
713 if (parentFuture.d.hasException()) {
715 if constexpr (
std::is_void_v<ArgType>) {
716 handleAllExceptions();
718 handleException<ArgType>();
720 }
else if (parentFuture.d.isChainCanceled()) {
721 promise.future().cancel();
723 QtPrivate::fulfillPromise(promise, parentFuture);
729template<
class ArgType>
733 Q_ASSERT(parentFuture.d.hasException());
734 parentFuture.d.exceptionStore().rethrowException();
735 }
catch (
const ArgType &e) {
738 if constexpr (
std::is_void_v<ResultType>)
741 promise.addResult(handler(e));
743 promise.setException(
std::current_exception());
748 promise.setException(
std::current_exception());
752template<
class Function,
class ResultType>
756 Q_ASSERT(parentFuture.d.hasException());
757 parentFuture.d.exceptionStore().rethrowException();
760 QtPrivate::fulfillPromise(promise,
std::forward<Function>(handler));
762 promise.setException(
std::current_exception());
769template<
class Function,
class ResultType>
773 template<
class F = Function>
778 auto canceledContinuation = [promise = QPromise(fi), handler =
std::forward<F>(handler)](
779 const QFutureInterfaceBase &parentData)
mutable {
781 run(
std::forward<F>(handler), parentFuture,
std::move(promise));
783 future->d.setContinuation(ContinuationWrapper(std::move(canceledContinuation)), fi.d,
784 QFutureInterfaceBase::ContinuationType::OnCanceled);
787 template<
class F = Function>
793 auto canceledContinuation = [handler = std::forward<F>(handler),
794 parentFuture = *future, promise = QPromise(fi)]()
mutable {
795 run(std::forward<F>(handler), parentFuture, std::move(promise));
798 future->d.setContinuation(context, ContinuationWrapper(std::move(canceledContinuation)),
799 QVariant::fromValue(fi),
800 QFutureInterfaceBase::ContinuationType::OnCanceled);
803 template<
class F = Function>
804 static void run(F &&handler, QFuture<ResultType> &parentFuture, QPromise<ResultType> &&promise)
808 if (parentFuture.isCanceled()) {
809#ifndef QT_NO_EXCEPTIONS
810 if (parentFuture.d.hasException()) {
812 promise.setException(parentFuture.d.exceptionStore().exception());
816 QtPrivate::fulfillPromise(promise,
std::forward<F>(handler));
817#ifndef QT_NO_EXCEPTIONS
819 promise.setException(
std::current_exception());
824 QtPrivate::fulfillPromise(promise, parentFuture);
838 using ResultType =
typename QtPrivate::Future<std::decay_t<T>>::type;
839 using NestedType =
typename QtPrivate::Future<ResultType>::type;
840 QFutureInterface<NestedType> promise(QFutureInterfaceBase::State::Pending);
842 outer->then([promise](
const QFuture<ResultType> &outerFuture)
mutable {
846 Q_ASSERT(outerFuture.isFinished());
847#ifndef QT_NO_EXCEPTIONS
848 if (outerFuture.d.hasException()) {
849 promise.reportStarted();
850 promise.reportException(outerFuture.d.exceptionStore().exception());
851 promise.reportFinished();
856 promise.reportStarted();
857 ResultType nestedFuture = outerFuture.result();
859 nestedFuture.then([promise] (
const QFuture<NestedType> &nested)
mutable {
860#ifndef QT_NO_EXCEPTIONS
861 if (nested.d.hasException()) {
862 promise.reportException(nested.d.exceptionStore().exception());
866 if constexpr (!std::is_void_v<NestedType>)
867 promise.reportResults(nested.results());
869 promise.reportFinished();
870 }).onCanceled([promise] ()
mutable {
871 promise.reportCanceled();
872 promise.reportFinished();
874 }).onCanceled([promise]()
mutable {
876 promise.reportStarted();
877 promise.reportCanceled();
878 promise.reportFinished();
880 return promise.future();
884template<
typename ValueType>
888 promise.reportStarted();
889 promise.reportResults(values);
890 promise.reportFinished();
891 return promise.future();
898template<
class Signal>
904 using ArgsType = ArgsType<Signal>;
905 QFutureInterface<ArgsType> promise;
906 promise.reportStarted();
908 promise.reportCanceled();
909 promise.reportFinished();
910 return promise.future();
913 using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
914 auto connections = std::make_shared<Connections>();
916 if constexpr (std::is_void_v<ArgsType>) {
918 QObject::connect(sender, signal, sender, [promise, connections]()
mutable {
919 QObject::disconnect(connections->first);
920 QObject::disconnect(connections->second);
921 promise.reportFinished();
924 connections->first = QObject::connect(sender, signal, sender,
925 [promise, connections](
auto... values)
mutable {
926 QObject::disconnect(connections->first);
927 QObject::disconnect(connections->second);
928 promise.reportResult(QtPrivate::createTuple(
929 std::move(values)...));
930 promise.reportFinished();
933 connections->first = QObject::connect(sender, signal, sender,
934 [promise, connections](ArgsType value)
mutable {
935 QObject::disconnect(connections->first);
936 QObject::disconnect(connections->second);
937 promise.reportResult(value);
938 promise.reportFinished();
942 if (!connections->first) {
943 promise.reportCanceled();
944 promise.reportFinished();
945 return promise.future();
948 connections->second =
949 QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]()
mutable {
950 QObject::disconnect(connections->first);
951 QObject::disconnect(connections->second);
952 promise.reportCanceled();
953 promise.reportFinished();
956 return promise.future();
968template<
typename Container, if_container_with_input_iterators<Container> =
true>
973 using ValueType = ContainedType<Container>;
974 if constexpr (std::is_convertible_v<q20::remove_cvref_t<Container>, QList<ValueType>>) {
975 return QtPrivate::makeReadyRangeFutureImpl(container);
977 return QtPrivate::makeReadyRangeFutureImpl(QList<ValueType>{std::cbegin(container),
978 std::cend(container)});
991 QFutureInterface<std::decay_t<T>> promise;
992 promise.reportStarted();
993 promise.reportResult(
std::forward<T>(value));
994 promise.reportFinished();
996 return promise.future();
1001#if QT_DEPRECATED_SINCE(6
, 10
)
1020#ifndef QT_NO_EXCEPTIONS
1022template<
typename T =
void>
1026 promise.reportStarted();
1027 promise.reportException(exception);
1028 promise.reportFinished();
1030 return promise.future();
1033template<
typename T =
void>
1039 return makeExceptionalFuture<T>(
std::current_exception());
1050template<
typename ResultFutures>
1053 using ValueType =
typename ResultFutures::value_type;
1057 template<
typename T = ValueType>
1061 const auto oldRemaining = remaining.fetchAndSubRelaxed(1);
1062 Q_ASSERT(oldRemaining > 0);
1063 if (oldRemaining <= 1) {
1074template<
typename ResultType>
1077 using ValueType = ResultType;
1082 if (!ready.fetchAndStoreRelaxed(
true)) {
1092template<qsizetype Index,
typename ContextType,
typename... Ts>
1094 const std::tuple<Ts...> &t)
1096 auto future =
std::get<Index>(t);
1097 using ResultType =
typename ContextType::ValueType;
1099 future.then([context=context](
const std::tuple_element_t<Index, std::tuple<Ts...>> &f) {
1100 context->checkForCompletion(Index, ResultType {
std::in_place_index<Index>, f });
1101 }).onCanceled([context=context, future]() {
1102 context->checkForCompletion(Index, ResultType {
std::in_place_index<Index>, future });
1105 if constexpr (Index != 0)
1106 addCompletionHandlersImpl<Index - 1, ContextType, Ts...>(context, t);
1109template<
typename ContextType,
typename... Ts>
1112 constexpr qsizetype size =
std::tuple_size<
std::tuple<Ts...>>::value;
1113 addCompletionHandlersImpl<size - 1, ContextType, Ts...>(context, t);
1141template<
typename OutputSequence,
typename... Futures>
1144 constexpr qsizetype size =
sizeof...(Futures);
1146 context->futures.resize(size);
1147 context->promise.start();
1149 QtPrivate::addCompletionHandlers(context,
std::make_tuple(
std::forward<Futures>(futures)...));
1151 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)
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 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... >)
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)
QPromise< ResultType > promise
void checkForCompletion(qsizetype, T &&result)