Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:24

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