File indexing completed on 2025-01-18 10:07:24
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/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
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
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
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
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
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
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
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
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);
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
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
0367 {
0368 QThreadPool *pool = threadPool ? threadPool : QThreadPool::globalInstance();
0369 pool->start(this);
0370 }
0371
0372 void run() override
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
0434
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
0449
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
0472
0473
0474
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
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
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
0554
0555
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
0583
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
0612
0613
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
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
0757
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
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
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
0851
0852
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
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 }
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
0979
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();
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
1017
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
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
1052
1053 }
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) {
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
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
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
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 }
1201
1202 QT_END_NAMESPACE