Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:24:15

0001 // Copyright (C) 2020 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QFUTURE_H
0005 #error Do not include qfuture_impl.h directly
0006 #endif
0007 
0008 #if 0
0009 #pragma qt_sync_skip_header_check
0010 #pragma qt_sync_stop_processing
0011 #endif
0012 
0013 #include <QtCore/qglobal.h>
0014 #include <QtCore/qfunctionaltools_impl.h>
0015 #include <QtCore/qfutureinterface.h>
0016 #include <QtCore/qthreadpool.h>
0017 #include <QtCore/qexception.h>
0018 #include <QtCore/qpromise.h>
0019 
0020 #include <memory>
0021 
0022 QT_BEGIN_NAMESPACE
0023 
0024 //
0025 // forward declarations
0026 //
0027 template<class T>
0028 class QFuture;
0029 template<class T>
0030 class QFutureInterface;
0031 template<class T>
0032 class QPromise;
0033 
0034 namespace QtFuture {
0035 
0036 enum class Launch { Sync, Async, Inherit };
0037 
0038 template<class T>
0039 struct WhenAnyResult
0040 {
0041     qsizetype index = -1;
0042     QFuture<T> future;
0043 };
0044 
0045 // Deduction guide
0046 template<class T>
0047 WhenAnyResult(qsizetype, const QFuture<T> &) -> WhenAnyResult<T>;
0048 }
0049 
0050 namespace QtPrivate {
0051 
0052 template<class T>
0053 using EnableForVoid = std::enable_if_t<std::is_same_v<T, void>>;
0054 
0055 template<class T>
0056 using EnableForNonVoid = std::enable_if_t<!std::is_same_v<T, void>>;
0057 
0058 template<typename F, typename Arg, typename Enable = void>
0059 struct ResultTypeHelper
0060 {
0061 };
0062 
0063 // The callable takes an argument of type Arg
0064 template<typename F, typename Arg>
0065 struct ResultTypeHelper<
0066         F, Arg, typename std::enable_if_t<!std::is_invocable_v<std::decay_t<F>, QFuture<Arg>>>>
0067 {
0068     using ResultType = std::invoke_result_t<std::decay_t<F>, std::decay_t<Arg>>;
0069 };
0070 
0071 // The callable takes an argument of type QFuture<Arg>
0072 template<class F, class Arg>
0073 struct ResultTypeHelper<
0074         F, Arg, typename std::enable_if_t<std::is_invocable_v<std::decay_t<F>, QFuture<Arg>>>>
0075 {
0076     using ResultType = std::invoke_result_t<std::decay_t<F>, QFuture<Arg>>;
0077 };
0078 
0079 // The callable takes an argument of type QFuture<void>
0080 template<class F>
0081 struct ResultTypeHelper<
0082         F, void, typename std::enable_if_t<std::is_invocable_v<std::decay_t<F>, QFuture<void>>>>
0083 {
0084     using ResultType = std::invoke_result_t<std::decay_t<F>, QFuture<void>>;
0085 };
0086 
0087 // The callable doesn't take argument
0088 template<class F>
0089 struct ResultTypeHelper<
0090         F, void, typename std::enable_if_t<!std::is_invocable_v<std::decay_t<F>, QFuture<void>>>>
0091 {
0092     using ResultType = std::invoke_result_t<std::decay_t<F>>;
0093 };
0094 
0095 // Helpers to remove QPrivateSignal argument from the list of arguments
0096 
0097 template<class T, class Enable = void>
0098 inline constexpr bool IsPrivateSignalArg = false;
0099 
0100 template<class T>
0101 inline constexpr bool IsPrivateSignalArg<T, typename std::enable_if_t<
0102         // finds injected-class-name, the 'class' avoids falling into the rules of [class.qual]/2:
0103         std::is_class_v<class T::QPrivateSignal>
0104     >> = true;
0105 
0106 template<class Tuple, std::size_t... I>
0107 auto cutTuple(Tuple &&t, std::index_sequence<I...>)
0108 {
0109     return std::make_tuple(std::get<I>(t)...);
0110 }
0111 
0112 template<class Arg, class... Args>
0113 auto createTuple(Arg &&arg, Args &&... args)
0114 {
0115     using TupleType = std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>;
0116     constexpr auto Size = sizeof...(Args); // One less than the size of all arguments
0117     if constexpr (QtPrivate::IsPrivateSignalArg<std::tuple_element_t<Size, TupleType>>) {
0118         if constexpr (Size == 1) {
0119             return std::forward<Arg>(arg);
0120         } else {
0121             return cutTuple(std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...),
0122                             std::make_index_sequence<Size>());
0123         }
0124     } else {
0125         return std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...);
0126     }
0127 }
0128 
0129 // Helpers to resolve argument types of callables.
0130 
0131 template<class Arg, class... Args>
0132 using FilterLastPrivateSignalArg =
0133         std::conditional_t<(sizeof...(Args) > 0),
0134                            std::invoke_result_t<decltype(createTuple<Arg, Args...>), Arg, Args...>,
0135                            std::conditional_t<IsPrivateSignalArg<Arg>, void, Arg>>;
0136 
0137 template<typename...>
0138 struct ArgsType;
0139 
0140 template<typename Arg, typename... Args>
0141 struct ArgsType<Arg, Args...>
0142 {
0143     using First = Arg;
0144     using PromiseType = void;
0145     using IsPromise = std::false_type;
0146     static const bool HasExtraArgs = (sizeof...(Args) > 0);
0147     using AllArgs = FilterLastPrivateSignalArg<std::decay_t<Arg>, std::decay_t<Args>...>;
0148 
0149     template<class Class, class Callable>
0150     static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class, Arg, Args...>;
0151 };
0152 
0153 template<typename Arg, typename... Args>
0154 struct ArgsType<QPromise<Arg> &, Args...>
0155 {
0156     using First = QPromise<Arg> &;
0157     using PromiseType = Arg;
0158     using IsPromise = std::true_type;
0159     static const bool HasExtraArgs = (sizeof...(Args) > 0);
0160     using AllArgs = FilterLastPrivateSignalArg<QPromise<Arg>, std::decay_t<Args>...>;
0161 
0162     template<class Class, class Callable>
0163     static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class, QPromise<Arg> &, Args...>;
0164 };
0165 
0166 template<>
0167 struct ArgsType<>
0168 {
0169     using First = void;
0170     using PromiseType = void;
0171     using IsPromise = std::false_type;
0172     static const bool HasExtraArgs = false;
0173     using AllArgs = void;
0174 
0175     template<class Class, class Callable>
0176     static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class>;
0177 };
0178 
0179 template<typename F>
0180 struct ArgResolver : ArgResolver<decltype(&std::decay_t<F>::operator())>
0181 {
0182 };
0183 
0184 template<typename F>
0185 struct ArgResolver<std::reference_wrapper<F>> : ArgResolver<decltype(&std::decay_t<F>::operator())>
0186 {
0187 };
0188 
0189 template<typename R, typename... Args>
0190 struct ArgResolver<R(Args...)> : public ArgsType<Args...>
0191 {
0192 };
0193 
0194 template<typename R, typename... Args>
0195 struct ArgResolver<R (*)(Args...)> : public ArgsType<Args...>
0196 {
0197 };
0198 
0199 template<typename R, typename... Args>
0200 struct ArgResolver<R (*&)(Args...)> : public ArgsType<Args...>
0201 {
0202 };
0203 
0204 template<typename R, typename... Args>
0205 struct ArgResolver<R (* const)(Args...)> : public ArgsType<Args...>
0206 {
0207 };
0208 
0209 template<typename R, typename... Args>
0210 struct ArgResolver<R (&)(Args...)> : public ArgsType<Args...>
0211 {
0212 };
0213 
0214 template<typename Class, typename R, typename... Args>
0215 struct ArgResolver<R (Class::*)(Args...)> : public ArgsType<Args...>
0216 {
0217 };
0218 
0219 template<typename Class, typename R, typename... Args>
0220 struct ArgResolver<R (Class::*)(Args...) noexcept> : public ArgsType<Args...>
0221 {
0222 };
0223 
0224 template<typename Class, typename R, typename... Args>
0225 struct ArgResolver<R (Class::*)(Args...) const> : public ArgsType<Args...>
0226 {
0227 };
0228 
0229 template<typename Class, typename R, typename... Args>
0230 struct ArgResolver<R (Class::*)(Args...) const noexcept> : public ArgsType<Args...>
0231 {
0232 };
0233 
0234 template<typename Class, typename R, typename... Args>
0235 struct ArgResolver<R (Class::* const)(Args...) const> : public ArgsType<Args...>
0236 {
0237 };
0238 
0239 template<typename Class, typename R, typename... Args>
0240 struct ArgResolver<R (Class::* const)(Args...) const noexcept> : public ArgsType<Args...>
0241 {
0242 };
0243 
0244 template<class Class, class Callable>
0245 using EnableIfInvocable = std::enable_if_t<
0246         QtPrivate::ArgResolver<Callable>::template CanInvokeWithArgs<Class, Callable>>;
0247 
0248 template<class T>
0249 inline constexpr bool isQFutureV = false;
0250 
0251 template<class T>
0252 inline constexpr bool isQFutureV<QFuture<T>> = true;
0253 
0254 template<class T>
0255 using isQFuture = std::bool_constant<isQFutureV<T>>;
0256 
0257 template<class T>
0258 struct Future
0259 {
0260 };
0261 
0262 template<class T>
0263 struct Future<QFuture<T>>
0264 {
0265     using type = T;
0266 };
0267 
0268 template<class... Args>
0269 using NotEmpty = std::bool_constant<(sizeof...(Args) > 0)>;
0270 
0271 template<class Sequence>
0272 using IsRandomAccessible =
0273         std::is_convertible<typename std::iterator_traits<std::decay_t<decltype(
0274                                     std::begin(std::declval<Sequence>()))>>::iterator_category,
0275                             std::random_access_iterator_tag>;
0276 
0277 template<class Sequence>
0278 using HasInputIterator =
0279         std::is_convertible<typename std::iterator_traits<std::decay_t<decltype(
0280                                     std::begin(std::declval<Sequence>()))>>::iterator_category,
0281                             std::input_iterator_tag>;
0282 
0283 template<class Iterator>
0284 using IsForwardIterable =
0285         std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category,
0286                             std::forward_iterator_tag>;
0287 
0288 template<typename Function, typename ResultType, typename ParentResultType>
0289 class CompactContinuation : private CompactStorage<Function>
0290 {
0291     Q_DISABLE_COPY_MOVE(CompactContinuation)
0292 public:
0293     using Storage = CompactStorage<Function>;
0294 
0295     template<typename F = Function>
0296     CompactContinuation(F &&func, const QFuture<ParentResultType> &f, QPromise<ResultType> &&p)
0297         : Storage{std::forward<F>(func)}, promise(std::move(p)), parentFuture(f), type(Type::Sync)
0298     {
0299     }
0300 
0301     template<typename F = Function>
0302     CompactContinuation(F &&func, const QFuture<ParentResultType> &f, QPromise<ResultType> &&p,
0303                  QThreadPool *pool)
0304         : Storage{std::forward<F>(func)}, promise(std::move(p)), parentFuture(f),
0305           threadPool(pool), type(Type::Async)
0306     {
0307         runObj = QRunnable::create([continuation = this] {
0308             continuation->runFunction();
0309             delete continuation;
0310         });
0311         runObj->setAutoDelete(false);
0312     }
0313 
0314     ~CompactContinuation() { delete runObj; }
0315 
0316     bool execute();
0317 
0318     QRunnable *runnable() const { return runObj; }
0319 
0320     template<typename F = Function>
0321     static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &fi,
0322                        QtFuture::Launch policy);
0323 
0324     template<typename F = Function>
0325     static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &fi,
0326                        QThreadPool *pool);
0327 
0328     template<typename F = Function>
0329     static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &fi,
0330                        QObject *context);
0331 
0332 private:
0333     void fulfillPromiseWithResult();
0334     void fulfillVoidPromise();
0335     void fulfillPromiseWithVoidResult();
0336 
0337     template<class... Args>
0338     void fulfillPromise(Args &&... args);
0339 
0340 protected:
0341     void runImpl()
0342     {
0343         if (type == Type::Sync) {
0344             runFunction();
0345         } else {
0346             Q_ASSERT(runObj);
0347             QThreadPool *pool = threadPool ? threadPool : QThreadPool::globalInstance();
0348             pool->start(runObj);
0349         }
0350     }
0351 
0352     void runFunction();
0353 
0354 protected:
0355     enum class Type : quint8 {
0356         Sync,
0357         Async
0358     };
0359 
0360     QPromise<ResultType> promise;
0361     QFuture<ParentResultType> parentFuture;
0362     QThreadPool *threadPool = nullptr;
0363     QRunnable *runObj = nullptr;
0364     const Type type;
0365 };
0366 
0367 #ifndef QT_NO_EXCEPTIONS
0368 
0369 template<class Function, class ResultType>
0370 class FailureHandler
0371 {
0372 public:
0373     template<typename F = Function>
0374     static void create(F &&function, QFuture<ResultType> *future,
0375                        const QFutureInterface<ResultType> &fi);
0376 
0377     template<typename F = Function>
0378     static void create(F &&function, QFuture<ResultType> *future, QFutureInterface<ResultType> &fi,
0379                        QObject *context);
0380 
0381     template<typename F = Function>
0382     FailureHandler(F &&func, const QFuture<ResultType> &f, QPromise<ResultType> &&p)
0383         : promise(std::move(p)), parentFuture(f), handler(std::forward<F>(func))
0384     {
0385     }
0386 
0387 public:
0388     void run();
0389 
0390 private:
0391     template<class ArgType>
0392     void handleException();
0393     void handleAllExceptions();
0394 
0395 private:
0396     QPromise<ResultType> promise;
0397     QFuture<ResultType> parentFuture;
0398     Function handler;
0399 };
0400 
0401 #endif
0402 
0403 template<typename Function, typename ResultType, typename ParentResultType>
0404 void CompactContinuation<Function, ResultType, ParentResultType>::runFunction()
0405 {
0406     promise.start();
0407 
0408     Q_ASSERT(parentFuture.isFinished());
0409 
0410 #ifndef QT_NO_EXCEPTIONS
0411     try {
0412 #endif
0413         if constexpr (!std::is_void_v<ResultType>) {
0414             if constexpr (std::is_void_v<ParentResultType>) {
0415                 fulfillPromiseWithVoidResult();
0416             } else if constexpr (std::is_invocable_v<Function, ParentResultType>) {
0417                 fulfillPromiseWithResult();
0418             } else {
0419                 // This assert normally should never fail, this is to make sure
0420                 // that nothing unexpected happened.
0421                 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
0422                               "The continuation is not invocable with the provided arguments");
0423                 fulfillPromise(parentFuture);
0424             }
0425         } else {
0426             if constexpr (std::is_void_v<ParentResultType>) {
0427                 if constexpr (std::is_invocable_v<Function, QFuture<void>>)
0428                     this->object()(parentFuture);
0429                 else
0430                     this->object()();
0431             } else if constexpr (std::is_invocable_v<Function, ParentResultType>) {
0432                 fulfillVoidPromise();
0433             } else {
0434                 // This assert normally should never fail, this is to make sure
0435                 // that nothing unexpected happened.
0436                 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
0437                               "The continuation is not invocable with the provided arguments");
0438                 this->object()(parentFuture);
0439             }
0440         }
0441 #ifndef QT_NO_EXCEPTIONS
0442     } catch (...) {
0443         promise.setException(std::current_exception());
0444     }
0445 #endif
0446     promise.finish();
0447 }
0448 
0449 template<typename Function, typename ResultType, typename ParentResultType>
0450 bool CompactContinuation<Function, ResultType, ParentResultType>::execute()
0451 {
0452     Q_ASSERT(parentFuture.isFinished());
0453 
0454     if (parentFuture.d.isChainCanceled()) {
0455 #ifndef QT_NO_EXCEPTIONS
0456         if (parentFuture.d.hasException()) {
0457             // If the continuation doesn't take a QFuture argument, propagate the exception
0458             // to the caller, by reporting it. If the continuation takes a QFuture argument,
0459             // the user may want to catch the exception inside the continuation, to not
0460             // interrupt the continuation chain, so don't report anything yet.
0461             if constexpr (!std::is_invocable_v<std::decay_t<Function>, QFuture<ParentResultType>>) {
0462                 promise.start();
0463                 promise.setException(parentFuture.d.exceptionStore().exception());
0464                 promise.finish();
0465                 return false;
0466             }
0467         } else
0468 #endif
0469         {
0470             promise.start();
0471             promise.future().cancel();
0472             promise.finish();
0473             return false;
0474         }
0475     }
0476 
0477     runImpl();
0478     return true;
0479 }
0480 
0481 // Workaround for keeping move-only lambdas inside std::function
0482 template<class Function>
0483 struct ContinuationWrapper
0484 {
0485     ContinuationWrapper(Function &&f) : function(std::move(f)) { }
0486     ContinuationWrapper(const ContinuationWrapper &other)
0487         : function(std::move(const_cast<ContinuationWrapper &>(other).function))
0488     {
0489         Q_ASSERT_X(false, "QFuture", "Continuation shouldn't be copied");
0490     }
0491     ContinuationWrapper(ContinuationWrapper &&other) = default;
0492     ContinuationWrapper &operator=(ContinuationWrapper &&) = default;
0493 
0494     void operator()(const QFutureInterfaceBase &parentData) { function(parentData); }
0495 
0496 private:
0497     Function function;
0498 };
0499 
0500 template<typename Function, typename ResultType, typename ParentResultType>
0501 template<typename F>
0502 void CompactContinuation<Function, ResultType, ParentResultType>::create(F &&func,
0503                                                                   QFuture<ParentResultType> *f,
0504                                                                   QFutureInterface<ResultType> &fi,
0505                                                                   QtFuture::Launch policy)
0506 {
0507     Q_ASSERT(f);
0508 
0509     QThreadPool *pool = nullptr;
0510 
0511     bool launchAsync = (policy == QtFuture::Launch::Async);
0512     if (policy == QtFuture::Launch::Inherit) {
0513         launchAsync = f->d.launchAsync();
0514 
0515         // If the parent future was using a custom thread pool, inherit it as well.
0516         if (launchAsync && f->d.threadPool()) {
0517             pool = f->d.threadPool();
0518             fi.setThreadPool(pool);
0519         }
0520     }
0521 
0522     fi.setLaunchAsync(launchAsync);
0523 
0524     auto continuation = [func = std::forward<F>(func), fi, promise_ = QPromise(fi), pool,
0525                          launchAsync](const QFutureInterfaceBase &parentData) mutable {
0526         const auto parent = QFutureInterface<ParentResultType>(parentData).future();
0527         CompactContinuation<Function, ResultType, ParentResultType> *continuationJob = nullptr;
0528         if (launchAsync) {
0529             auto asyncJob = new CompactContinuation<Function, ResultType, ParentResultType>(
0530                     std::forward<Function>(func), parent, std::move(promise_), pool);
0531             fi.setRunnable(asyncJob->runnable());
0532             continuationJob = asyncJob;
0533         } else {
0534             continuationJob = new CompactContinuation<Function, ResultType, ParentResultType>(
0535                     std::forward<Function>(func), parent, std::move(promise_));
0536         }
0537 
0538         bool isLaunched = continuationJob->execute();
0539         // If continuation is successfully launched, AsyncContinuation will be deleted
0540         // from the QRunnable's lambda. Synchronous continuation will be
0541         // executed immediately, so it's safe to always delete it here.
0542         if (!(launchAsync && isLaunched)) {
0543             delete continuationJob;
0544             continuationJob = nullptr;
0545         }
0546     };
0547     f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d);
0548 }
0549 
0550 template<typename Function, typename ResultType, typename ParentResultType>
0551 template<typename F>
0552 void CompactContinuation<Function, ResultType, ParentResultType>::create(F &&func,
0553                                                                   QFuture<ParentResultType> *f,
0554                                                                   QFutureInterface<ResultType> &fi,
0555                                                                   QThreadPool *pool)
0556 {
0557     Q_ASSERT(f);
0558 
0559     fi.setLaunchAsync(true);
0560     fi.setThreadPool(pool);
0561 
0562     auto continuation = [func = std::forward<F>(func), promise_ = QPromise(fi),
0563                          pool](const QFutureInterfaceBase &parentData) mutable {
0564         const auto parent = QFutureInterface<ParentResultType>(parentData).future();
0565         auto continuationJob = new CompactContinuation<Function, ResultType, ParentResultType>(
0566                 std::forward<Function>(func), parent, std::move(promise_), pool);
0567         bool isLaunched = continuationJob->execute();
0568         // If continuation is successfully launched, AsyncContinuation will be deleted
0569         // from the QRunnable's lambda.
0570         if (!isLaunched) {
0571             delete continuationJob;
0572             continuationJob = nullptr;
0573         }
0574     };
0575     f->d.setContinuation(ContinuationWrapper(std::move(continuation)), fi.d);
0576 }
0577 
0578 template <typename Continuation>
0579 void watchContinuation(const QObject *context, Continuation &&c, QFutureInterfaceBase &fi)
0580 {
0581     using Prototype = typename QtPrivate::Callable<Continuation>::Function;
0582     watchContinuationImpl(context,
0583                           QtPrivate::makeCallableObject<Prototype>(std::forward<Continuation>(c)),
0584                           fi);
0585 }
0586 
0587 template<typename Function, typename ResultType, typename ParentResultType>
0588 template<typename F>
0589 void CompactContinuation<Function, ResultType, ParentResultType>::create(F &&func,
0590                                                                   QFuture<ParentResultType> *f,
0591                                                                   QFutureInterface<ResultType> &fi,
0592                                                                   QObject *context)
0593 {
0594     Q_ASSERT(f);
0595     Q_ASSERT(context);
0596 
0597     // When the context object is destroyed, the signal-slot connection is broken and the
0598     // continuation callback is destroyed. The promise that is created in the capture list is
0599     // destroyed and, if it is not yet finished, cancelled.
0600     auto continuation = [func = std::forward<F>(func), parent = *f,
0601                          promise_ = QPromise(fi)]() mutable {
0602         CompactContinuation<Function, ResultType, ParentResultType> continuationJob(
0603                 std::forward<Function>(func), parent, std::move(promise_));
0604         continuationJob.execute();
0605     };
0606 
0607     QtPrivate::watchContinuation(context, std::move(continuation), f->d);
0608 }
0609 
0610 template<typename Function, typename ResultType, typename ParentResultType>
0611 void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromiseWithResult()
0612 {
0613     if constexpr (std::is_copy_constructible_v<ParentResultType>)
0614         fulfillPromise(parentFuture.result());
0615     else
0616         fulfillPromise(parentFuture.takeResult());
0617 }
0618 
0619 template<typename Function, typename ResultType, typename ParentResultType>
0620 void CompactContinuation<Function, ResultType, ParentResultType>::fulfillVoidPromise()
0621 {
0622     if constexpr (std::is_copy_constructible_v<ParentResultType>)
0623         this->object()(parentFuture.result());
0624     else
0625         this->object()(parentFuture.takeResult());
0626 }
0627 
0628 template<typename Function, typename ResultType, typename ParentResultType>
0629 void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromiseWithVoidResult()
0630 {
0631     if constexpr (std::is_invocable_v<Function, QFuture<void>>)
0632         fulfillPromise(parentFuture);
0633     else
0634         fulfillPromise();
0635 }
0636 
0637 template<typename Function, typename ResultType, typename ParentResultType>
0638 template<class... Args>
0639 void CompactContinuation<Function, ResultType, ParentResultType>::fulfillPromise(Args &&... args)
0640 {
0641     promise.addResult(std::invoke(this->object(), std::forward<Args>(args)...));
0642 }
0643 
0644 template<class T>
0645 void fulfillPromise(QPromise<T> &promise, QFuture<T> &future)
0646 {
0647     if constexpr (!std::is_void_v<T>) {
0648         if constexpr (std::is_copy_constructible_v<T>)
0649             promise.addResult(future.result());
0650         else
0651             promise.addResult(future.takeResult());
0652     }
0653 }
0654 
0655 template<class T, class Function>
0656 void fulfillPromise(QPromise<T> &promise, Function &&handler)
0657 {
0658     if constexpr (std::is_void_v<T>)
0659         handler();
0660     else
0661         promise.addResult(handler());
0662 }
0663 
0664 #ifndef QT_NO_EXCEPTIONS
0665 
0666 template<class Function, class ResultType>
0667 template<class F>
0668 void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
0669                                                   const QFutureInterface<ResultType> &fi)
0670 {
0671     Q_ASSERT(future);
0672 
0673     auto failureContinuation = [function = std::forward<F>(function), promise_ = QPromise(fi)](
0674                                        const QFutureInterfaceBase &parentData) mutable {
0675         const auto parent = QFutureInterface<ResultType>(parentData).future();
0676         FailureHandler<Function, ResultType> failureHandler(std::forward<Function>(function),
0677                                                             parent, std::move(promise_));
0678         failureHandler.run();
0679     };
0680 
0681     future->d.setContinuation(ContinuationWrapper(std::move(failureContinuation)));
0682 }
0683 
0684 template<class Function, class ResultType>
0685 template<class F>
0686 void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
0687                                                   QFutureInterface<ResultType> &fi,
0688                                                   QObject *context)
0689 {
0690     Q_ASSERT(future);
0691     Q_ASSERT(context);
0692     auto failureContinuation = [function = std::forward<F>(function),
0693                                 parent = *future, promise_ = QPromise(fi)]() mutable {
0694         FailureHandler<Function, ResultType> failureHandler(
0695                 std::forward<Function>(function), parent, std::move(promise_));
0696         failureHandler.run();
0697     };
0698 
0699     QtPrivate::watchContinuation(context, std::move(failureContinuation), future->d);
0700 }
0701 
0702 template<class Function, class ResultType>
0703 void FailureHandler<Function, ResultType>::run()
0704 {
0705     Q_ASSERT(parentFuture.isFinished());
0706 
0707     promise.start();
0708 
0709     if (parentFuture.d.hasException()) {
0710         using ArgType = typename QtPrivate::ArgResolver<Function>::First;
0711         if constexpr (std::is_void_v<ArgType>) {
0712             handleAllExceptions();
0713         } else {
0714             handleException<ArgType>();
0715         }
0716     } else if (parentFuture.d.isChainCanceled()) {
0717         promise.future().cancel();
0718     } else {
0719         QtPrivate::fulfillPromise(promise, parentFuture);
0720     }
0721     promise.finish();
0722 }
0723 
0724 template<class Function, class ResultType>
0725 template<class ArgType>
0726 void FailureHandler<Function, ResultType>::handleException()
0727 {
0728     try {
0729         Q_ASSERT(parentFuture.d.hasException());
0730         parentFuture.d.exceptionStore().rethrowException();
0731     } catch (const ArgType &e) {
0732         try {
0733             // Handle exceptions matching with the handler's argument type
0734             if constexpr (std::is_void_v<ResultType>)
0735                 handler(e);
0736             else
0737                 promise.addResult(handler(e));
0738         } catch (...) {
0739             promise.setException(std::current_exception());
0740         }
0741     } catch (...) {
0742         // Exception doesn't match with handler's argument type, propagate
0743         // the exception to be handled later.
0744         promise.setException(std::current_exception());
0745     }
0746 }
0747 
0748 template<class Function, class ResultType>
0749 void FailureHandler<Function, ResultType>::handleAllExceptions()
0750 {
0751     try {
0752         Q_ASSERT(parentFuture.d.hasException());
0753         parentFuture.d.exceptionStore().rethrowException();
0754     } catch (...) {
0755         try {
0756             QtPrivate::fulfillPromise(promise, std::forward<Function>(handler));
0757         } catch (...) {
0758             promise.setException(std::current_exception());
0759         }
0760     }
0761 }
0762 
0763 #endif // QT_NO_EXCEPTIONS
0764 
0765 template<class Function, class ResultType>
0766 class CanceledHandler
0767 {
0768 public:
0769     template<class F = Function>
0770     static void create(F &&handler, QFuture<ResultType> *future, QFutureInterface<ResultType> &fi)
0771     {
0772         Q_ASSERT(future);
0773 
0774         auto canceledContinuation = [promise = QPromise(fi), handler = std::forward<F>(handler)](
0775                                             const QFutureInterfaceBase &parentData) mutable {
0776             auto parentFuture = QFutureInterface<ResultType>(parentData).future();
0777             run(std::forward<F>(handler), parentFuture, std::move(promise));
0778         };
0779         future->d.setContinuation(ContinuationWrapper(std::move(canceledContinuation)));
0780     }
0781 
0782     template<class F = Function>
0783     static void create(F &&handler, QFuture<ResultType> *future, QFutureInterface<ResultType> &fi,
0784                        QObject *context)
0785     {
0786         Q_ASSERT(future);
0787         Q_ASSERT(context);
0788         auto canceledContinuation = [handler = std::forward<F>(handler),
0789                                      parentFuture = *future, promise = QPromise(fi)]() mutable {
0790             run(std::forward<F>(handler), parentFuture, std::move(promise));
0791         };
0792 
0793         QtPrivate::watchContinuation(context, std::move(canceledContinuation), future->d);
0794     }
0795 
0796     template<class F = Function>
0797     static void run(F &&handler, QFuture<ResultType> &parentFuture, QPromise<ResultType> &&promise)
0798     {
0799         promise.start();
0800 
0801         if (parentFuture.isCanceled()) {
0802 #ifndef QT_NO_EXCEPTIONS
0803             if (parentFuture.d.hasException()) {
0804                 // Propagate the exception to the result future
0805                 promise.setException(parentFuture.d.exceptionStore().exception());
0806             } else {
0807                 try {
0808 #endif
0809                     QtPrivate::fulfillPromise(promise, std::forward<F>(handler));
0810 #ifndef QT_NO_EXCEPTIONS
0811                 } catch (...) {
0812                     promise.setException(std::current_exception());
0813                 }
0814             }
0815 #endif
0816         } else {
0817             QtPrivate::fulfillPromise(promise, parentFuture);
0818         }
0819 
0820         promise.finish();
0821     }
0822 };
0823 
0824 struct UnwrapHandler
0825 {
0826     template<class T>
0827     static auto unwrapImpl(T *outer)
0828     {
0829         Q_ASSERT(outer);
0830 
0831         using ResultType = typename QtPrivate::Future<std::decay_t<T>>::type;
0832         using NestedType = typename QtPrivate::Future<ResultType>::type;
0833         QFutureInterface<NestedType> promise(QFutureInterfaceBase::State::Pending);
0834 
0835         outer->then([promise](const QFuture<ResultType> &outerFuture) mutable {
0836             // We use the .then([](QFuture<ResultType> outerFuture) {...}) version
0837             // (where outerFuture == *outer), to propagate the exception if the
0838             // outer future has failed.
0839             Q_ASSERT(outerFuture.isFinished());
0840 #ifndef QT_NO_EXCEPTIONS
0841             if (outerFuture.d.hasException()) {
0842                 promise.reportStarted();
0843                 promise.reportException(outerFuture.d.exceptionStore().exception());
0844                 promise.reportFinished();
0845                 return;
0846             }
0847 #endif
0848 
0849             promise.reportStarted();
0850             ResultType nestedFuture = outerFuture.result();
0851 
0852             nestedFuture.then([promise] (const QFuture<NestedType> &nested) mutable {
0853 #ifndef QT_NO_EXCEPTIONS
0854                 if (nested.d.hasException()) {
0855                     promise.reportException(nested.d.exceptionStore().exception());
0856                 } else
0857 #endif
0858                 {
0859                     if constexpr (!std::is_void_v<NestedType>)
0860                         promise.reportResults(nested.results());
0861                 }
0862                 promise.reportFinished();
0863             }).onCanceled([promise] () mutable {
0864                 promise.reportCanceled();
0865                 promise.reportFinished();
0866             });
0867         }).onCanceled([promise]() mutable {
0868             // propagate the cancellation of the outer future
0869             promise.reportStarted();
0870             promise.reportCanceled();
0871             promise.reportFinished();
0872         });
0873         return promise.future();
0874     }
0875 };
0876 
0877 template<typename ValueType>
0878 QFuture<ValueType> makeReadyRangeFutureImpl(const QList<ValueType> &values)
0879 {
0880     QFutureInterface<ValueType> promise;
0881     promise.reportStarted();
0882     promise.reportResults(values);
0883     promise.reportFinished();
0884     return promise.future();
0885 }
0886 
0887 } // namespace QtPrivate
0888 
0889 namespace QtFuture {
0890 
0891 template<class Signal>
0892 using ArgsType = typename QtPrivate::ArgResolver<Signal>::AllArgs;
0893 
0894 template<class Sender, class Signal, typename = QtPrivate::EnableIfInvocable<Sender, Signal>>
0895 static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
0896 {
0897     using ArgsType = ArgsType<Signal>;
0898     QFutureInterface<ArgsType> promise;
0899     promise.reportStarted();
0900     if (!sender) {
0901         promise.reportCanceled();
0902         promise.reportFinished();
0903         return promise.future();
0904     }
0905 
0906     using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
0907     auto connections = std::make_shared<Connections>();
0908 
0909     if constexpr (std::is_void_v<ArgsType>) {
0910         connections->first =
0911                 QObject::connect(sender, signal, sender, [promise, connections]() mutable {
0912                     QObject::disconnect(connections->first);
0913                     QObject::disconnect(connections->second);
0914                     promise.reportFinished();
0915                 });
0916     } else if constexpr (QtPrivate::ArgResolver<Signal>::HasExtraArgs) {
0917         connections->first = QObject::connect(sender, signal, sender,
0918                                               [promise, connections](auto... values) mutable {
0919                                                   QObject::disconnect(connections->first);
0920                                                   QObject::disconnect(connections->second);
0921                                                   promise.reportResult(QtPrivate::createTuple(
0922                                                           std::move(values)...));
0923                                                   promise.reportFinished();
0924                                               });
0925     } else {
0926         connections->first = QObject::connect(sender, signal, sender,
0927                                               [promise, connections](ArgsType value) mutable {
0928                                                   QObject::disconnect(connections->first);
0929                                                   QObject::disconnect(connections->second);
0930                                                   promise.reportResult(value);
0931                                                   promise.reportFinished();
0932                                               });
0933     }
0934 
0935     if (!connections->first) {
0936         promise.reportCanceled();
0937         promise.reportFinished();
0938         return promise.future();
0939     }
0940 
0941     connections->second =
0942             QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
0943                 QObject::disconnect(connections->first);
0944                 QObject::disconnect(connections->second);
0945                 promise.reportCanceled();
0946                 promise.reportFinished();
0947             });
0948 
0949     return promise.future();
0950 }
0951 
0952 template<typename Container>
0953 using if_container_with_input_iterators =
0954         std::enable_if_t<QtPrivate::HasInputIterator<Container>::value, bool>;
0955 
0956 template<typename Container>
0957 using ContainedType =
0958         typename std::iterator_traits<decltype(
0959                     std::cbegin(std::declval<Container&>()))>::value_type;
0960 
0961 template<typename Container, if_container_with_input_iterators<Container> = true>
0962 static QFuture<ContainedType<Container>> makeReadyRangeFuture(Container &&container)
0963 {
0964     // handle QList<T> separately, because reportResults() takes a QList
0965     // as an input
0966     using ValueType = ContainedType<Container>;
0967     if constexpr (std::is_convertible_v<q20::remove_cvref_t<Container>, QList<ValueType>>) {
0968         return QtPrivate::makeReadyRangeFutureImpl(container);
0969     } else {
0970         return QtPrivate::makeReadyRangeFutureImpl(QList<ValueType>{std::cbegin(container),
0971                                                                     std::cend(container)});
0972     }
0973 }
0974 
0975 template<typename ValueType>
0976 static QFuture<ValueType> makeReadyRangeFuture(std::initializer_list<ValueType> values)
0977 {
0978     return QtPrivate::makeReadyRangeFutureImpl(QList<ValueType>{values});
0979 }
0980 
0981 template<typename T>
0982 static QFuture<std::decay_t<T>> makeReadyValueFuture(T &&value)
0983 {
0984     QFutureInterface<std::decay_t<T>> promise;
0985     promise.reportStarted();
0986     promise.reportResult(std::forward<T>(value));
0987     promise.reportFinished();
0988 
0989     return promise.future();
0990 }
0991 
0992 Q_CORE_EXPORT QFuture<void> makeReadyVoidFuture(); // implemented in qfutureinterface.cpp
0993 
0994 #if QT_DEPRECATED_SINCE(6, 10)
0995 template<typename T, typename = QtPrivate::EnableForNonVoid<T>>
0996 QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyValueFuture() instead.")
0997 static QFuture<std::decay_t<T>> makeReadyFuture(T &&value)
0998 {
0999     return makeReadyValueFuture(std::forward<T>(value));
1000 }
1001 
1002 // the void specialization is moved to the end of qfuture.h, because it now
1003 // uses makeReadyVoidFuture() and required QFuture<void> to be defined.
1004 
1005 template<typename T>
1006 QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyRangeFuture() instead.")
1007 static QFuture<T> makeReadyFuture(const QList<T> &values)
1008 {
1009     return makeReadyRangeFuture(values);
1010 }
1011 #endif // QT_DEPRECATED_SINCE(6, 10)
1012 
1013 #ifndef QT_NO_EXCEPTIONS
1014 
1015 template<typename T = void>
1016 static QFuture<T> makeExceptionalFuture(std::exception_ptr exception)
1017 {
1018     QFutureInterface<T> promise;
1019     promise.reportStarted();
1020     promise.reportException(exception);
1021     promise.reportFinished();
1022 
1023     return promise.future();
1024 }
1025 
1026 template<typename T = void>
1027 static QFuture<T> makeExceptionalFuture(const QException &exception)
1028 {
1029     try {
1030         exception.raise();
1031     } catch (...) {
1032         return makeExceptionalFuture<T>(std::current_exception());
1033     }
1034     Q_UNREACHABLE();
1035 }
1036 
1037 #endif // QT_NO_EXCEPTIONS
1038 
1039 } // namespace QtFuture
1040 
1041 namespace QtPrivate {
1042 
1043 template<typename ResultFutures>
1044 struct WhenAllContext
1045 {
1046     using ValueType = typename ResultFutures::value_type;
1047 
1048     explicit WhenAllContext(qsizetype size) : remaining(size) {}
1049 
1050     template<typename T = ValueType>
1051     void checkForCompletion(qsizetype index, T &&future)
1052     {
1053         futures[index] = std::forward<T>(future);
1054         const auto oldRemaining = remaining.fetchAndSubRelaxed(1);
1055         Q_ASSERT(oldRemaining > 0);
1056         if (oldRemaining <= 1) { // that was the last one
1057             promise.addResult(futures);
1058             promise.finish();
1059         }
1060     }
1061 
1062     QAtomicInteger<qsizetype> remaining;
1063     QPromise<ResultFutures> promise;
1064     ResultFutures futures;
1065 };
1066 
1067 template<typename ResultType>
1068 struct WhenAnyContext
1069 {
1070     using ValueType = ResultType;
1071 
1072     template<typename T = ResultType, typename = EnableForNonVoid<T>>
1073     void checkForCompletion(qsizetype, T &&result)
1074     {
1075         if (!ready.fetchAndStoreRelaxed(true)) {
1076             promise.addResult(std::forward<T>(result));
1077             promise.finish();
1078         }
1079     }
1080 
1081     QAtomicInt ready = false;
1082     QPromise<ResultType> promise;
1083 };
1084 
1085 template<qsizetype Index, typename ContextType, typename... Ts>
1086 void addCompletionHandlersImpl(const std::shared_ptr<ContextType> &context,
1087                                const std::tuple<Ts...> &t)
1088 {
1089     auto future = std::get<Index>(t);
1090     using ResultType = typename ContextType::ValueType;
1091     // Need context=context so that the compiler does not infer the captured variable's type as 'const'
1092     future.then([context=context](const std::tuple_element_t<Index, std::tuple<Ts...>> &f) {
1093         context->checkForCompletion(Index, ResultType { std::in_place_index<Index>, f });
1094     }).onCanceled([context=context, future]() {
1095         context->checkForCompletion(Index, ResultType { std::in_place_index<Index>, future });
1096     });
1097 
1098     if constexpr (Index != 0)
1099         addCompletionHandlersImpl<Index - 1, ContextType, Ts...>(context, t);
1100 }
1101 
1102 template<typename ContextType, typename... Ts>
1103 void addCompletionHandlers(const std::shared_ptr<ContextType> &context, const std::tuple<Ts...> &t)
1104 {
1105     constexpr qsizetype size = std::tuple_size<std::tuple<Ts...>>::value;
1106     addCompletionHandlersImpl<size - 1, ContextType, Ts...>(context, t);
1107 }
1108 
1109 template<typename OutputSequence, typename InputIt, typename ValueType,
1110          std::enable_if_t<std::conjunction_v<IsForwardIterable<InputIt>, isQFuture<ValueType>>,
1111                           bool> = true>
1112 QFuture<OutputSequence> whenAllImpl(InputIt first, InputIt last)
1113 {
1114     const qsizetype size = std::distance(first, last);
1115     if (size == 0)
1116         return QtFuture::makeReadyValueFuture(OutputSequence());
1117 
1118     const auto context = std::make_shared<QtPrivate::WhenAllContext<OutputSequence>>(size);
1119     context->futures.resize(size);
1120     context->promise.start();
1121 
1122     qsizetype idx = 0;
1123     for (auto it = first; it != last; ++it, ++idx) {
1124         // Need context=context so that the compiler does not infer the captured variable's type as 'const'
1125         it->then([context=context, idx](const ValueType &f) {
1126             context->checkForCompletion(idx, f);
1127         }).onCanceled([context=context, idx, f = *it] {
1128             context->checkForCompletion(idx, f);
1129         });
1130     }
1131     return context->promise.future();
1132 }
1133 
1134 template<typename OutputSequence, typename... Futures>
1135 QFuture<OutputSequence> whenAllImpl(Futures &&... futures)
1136 {
1137     constexpr qsizetype size = sizeof...(Futures);
1138     const auto context = std::make_shared<QtPrivate::WhenAllContext<OutputSequence>>(size);
1139     context->futures.resize(size);
1140     context->promise.start();
1141 
1142     QtPrivate::addCompletionHandlers(context, std::make_tuple(std::forward<Futures>(futures)...));
1143 
1144     return context->promise.future();
1145 }
1146 
1147 template<typename InputIt, typename ValueType,
1148          std::enable_if_t<std::conjunction_v<IsForwardIterable<InputIt>, isQFuture<ValueType>>,
1149                           bool> = true>
1150 QFuture<QtFuture::WhenAnyResult<typename Future<ValueType>::type>> whenAnyImpl(InputIt first,
1151                                                                                InputIt last)
1152 {
1153     using PackagedType = typename Future<ValueType>::type;
1154     using ResultType = QtFuture::WhenAnyResult<PackagedType>;
1155 
1156     const qsizetype size = std::distance(first, last);
1157     if (size == 0) {
1158         return QtFuture::makeReadyValueFuture(
1159                 QtFuture::WhenAnyResult { qsizetype(-1), QFuture<PackagedType>() });
1160     }
1161 
1162     const auto context = std::make_shared<QtPrivate::WhenAnyContext<ResultType>>();
1163     context->promise.start();
1164 
1165     qsizetype idx = 0;
1166     for (auto it = first; it != last; ++it, ++idx) {
1167         // Need context=context so that the compiler does not infer the captured variable's type as 'const'
1168         it->then([context=context, idx](const ValueType &f) {
1169             context->checkForCompletion(idx, QtFuture::WhenAnyResult { idx, f });
1170         }).onCanceled([context=context, idx, f = *it] {
1171             context->checkForCompletion(idx, QtFuture::WhenAnyResult { idx, f });
1172         });
1173     }
1174     return context->promise.future();
1175 }
1176 
1177 template<typename... Futures>
1178 QFuture<std::variant<std::decay_t<Futures>...>> whenAnyImpl(Futures &&... futures)
1179 {
1180     using ResultType = std::variant<std::decay_t<Futures>...>;
1181 
1182     const auto context = std::make_shared<QtPrivate::WhenAnyContext<ResultType>>();
1183     context->promise.start();
1184 
1185     QtPrivate::addCompletionHandlers(context, std::make_tuple(std::forward<Futures>(futures)...));
1186 
1187     return context->promise.future();
1188 }
1189 
1190 } // namespace QtPrivate
1191 
1192 QT_END_NAMESPACE