File indexing completed on 2025-12-15 10:24:15
0001
0002
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
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
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
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
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
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
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
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
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);
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
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
0420
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
0435
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
0458
0459
0460
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
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
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
0540
0541
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
0569
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
0598
0599
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
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
0743
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
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
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
0837
0838
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
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 }
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
0965
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();
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
1003
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
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
1038
1039 }
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) {
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
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
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
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 }
1191
1192 QT_END_NAMESPACE