5#error Do not include qfuture_impl.h directly
9#pragma qt_sync_skip_header_check
10#pragma qt_sync_stop_processing
13#include <QtCore/qglobal.h>
14#include <QtCore/qbasicfuturewatcher.h>
15#include <QtCore/qfutureinterface.h>
16#include <QtCore/qthreadpool.h>
17#include <QtCore/qexception.h>
18#include <QtCore/qpointer.h>
19#include <QtCore/qpromise.h>
59template<
typename F,
typename Arg,
typename Enable =
void>
65template<
typename F,
typename Arg>
67 F, Arg, typename
std::enable_if_t<!std::is_invocable_v<std::decay_t<F>, QFuture<Arg>>>>
69 using ResultType = std::invoke_result_t<std::decay_t<F>, std::decay_t<Arg>>;
73template<
class F,
class Arg>
75 F, Arg, typename
std::enable_if_t<std::is_invocable_v<std::decay_t<F>, QFuture<Arg>>>>
83 F,
void, typename
std::enable_if_t<std::is_invocable_v<std::decay_t<F>, QFuture<void>>>>
91 F,
void, typename
std::enable_if_t<!std::is_invocable_v<std::decay_t<F>, QFuture<void>>>>
93 using ResultType = std::invoke_result_t<std::decay_t<F>>;
98template<
class T,
class Enable =
void>
104 std::is_class_v<class T::QPrivateSignal>
107template<
class Tuple, std::size_t... I>
110 return std::make_tuple(std::get<I>(
t)...);
113template<
class Arg,
class... Args>
116 using TupleType = std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>;
117 constexpr auto Size =
sizeof...(Args);
118 if constexpr (QtPrivate::IsPrivateSignalArg<std::tuple_element_t<Size, TupleType>>) {
119 if constexpr (
Size == 1) {
120 return std::forward<Arg>(
arg);
122 return cutTuple(std::make_tuple(std::forward<Arg>(
arg), std::forward<Args>(
args)...),
123 std::make_index_sequence<Size>());
126 return std::make_tuple(std::forward<Arg>(
arg), std::forward<Args>(
args)...);
132template<
class Arg,
class... Args>
134 std::conditional_t<(
sizeof...(Args) > 0),
135 std::invoke_result_t<
decltype(
createTuple<Arg, Args...>), Arg, Args...>,
136 std::conditional_t<IsPrivateSignalArg<Arg>,
void, Arg>>;
141template<
typename Arg,
typename... Args>
147 static const bool HasExtraArgs = (
sizeof...(Args) > 0);
150 template<
class Class,
class Callable>
151 static const bool CanInvokeWithArgs = std::is_invocable_v<
Callable, Class, Arg, Args...>;
154template<
typename Arg,
typename... Args>
160 static const bool HasExtraArgs = (
sizeof...(Args) > 0);
163 template<
class Class,
class Callable>
164 static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class, QPromise<Arg> &, Args...>;
173 static const bool HasExtraArgs =
false;
176 template<
class Class,
class Callable>
177 static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class>;
190template<
typename R,
typename... Args>
195template<
typename R,
typename... Args>
200template<
typename R,
typename... Args>
205template<
typename R,
typename... Args>
210template<
typename R,
typename... Args>
215template<
typename Class,
typename R,
typename... Args>
220template<
typename Class,
typename R,
typename... Args>
225template<
typename Class,
typename R,
typename... Args>
230template<
typename Class,
typename R,
typename... Args>
235template<
typename Class,
typename R,
typename... Args>
240template<
typename Class,
typename R,
typename... Args>
245template<
class Class,
class Callable>
253inline constexpr bool isQFutureV<QFuture<T>> =
true;
269template<
class... Args>
270using NotEmpty = std::bool_constant<(
sizeof...(Args) > 0)>;
272template<
class Sequence>
274 std::is_convertible<
typename std::iterator_traits<std::decay_t<
decltype(
275 std::begin(std::declval<Sequence>()))>>::iterator_category,
276 std::random_access_iterator_tag>;
278template<
class Sequence>
280 std::is_convertible<
typename std::iterator_traits<std::decay_t<
decltype(
281 std::begin(std::declval<Sequence>()))>>::iterator_category,
282 std::input_iterator_tag>;
284template<
class Iterator>
286 std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category,
287 std::forward_iterator_tag>;
289template<
typename Function,
typename ResultType,
typename ParentResultType>
293 template<
typename F = Function>
302 template<
typename F = Function>
306 template<
typename F = Function>
310 template<
typename F = Function>
315 void fulfillPromiseWithResult();
316 void fulfillVoidPromise();
317 void fulfillPromiseWithVoidResult();
319 template<
class... Args>
320 void fulfillPromise(Args &&...
args);
333template<
typename Function,
typename ResultType,
typename ParentResultType>
337 template<
typename F = Function>
350template<
typename Function,
typename ResultType,
typename ParentResultType>
352 public Continuation<Function, ResultType, ParentResultType>
355 template<
typename F = Function>
382#ifndef QT_NO_EXCEPTIONS
384template<
class Function,
class ResultType>
388 template<
typename F = Function>
392 template<
typename F = Function>
396 template<
typename F = Function>
398 : promise(
std::move(
p)), parentFuture(
f), handler(
std::forward<F>(
func))
406 template<
class ArgType>
407 void handleException();
408 void handleAllExceptions();
418template<
typename Function,
typename ResultType,
typename ParentResultType>
423 Q_ASSERT(parentFuture.isFinished());
425#ifndef QT_NO_EXCEPTIONS
428 if constexpr (!std::is_void_v<ResultType>) {
429 if constexpr (std::is_void_v<ParentResultType>) {
430 fulfillPromiseWithVoidResult();
431 }
else if constexpr (std::is_invocable_v<Function, ParentResultType>) {
432 fulfillPromiseWithResult();
436 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
437 "The continuation is not invocable with the provided arguments");
441 if constexpr (std::is_void_v<ParentResultType>) {
442 if constexpr (std::is_invocable_v<Function, QFuture<void>>)
446 }
else if constexpr (std::is_invocable_v<Function, ParentResultType>) {
447 fulfillVoidPromise();
451 static_assert(std::is_invocable_v<Function, QFuture<ParentResultType>>,
452 "The continuation is not invocable with the provided arguments");
456#ifndef QT_NO_EXCEPTIONS
458 promise.setException(std::current_exception());
464template<
typename Function,
typename ResultType,
typename ParentResultType>
467 Q_ASSERT(parentFuture.isFinished());
469 if (parentFuture.d.isChainCanceled()) {
470#ifndef QT_NO_EXCEPTIONS
471 if (parentFuture.d.hasException()) {
478 promise.setException(parentFuture.d.exceptionStore().exception());
486 promise.future().cancel();
497template<
class Function>
504 Q_ASSERT_X(
false,
"QFuture",
"Continuation shouldn't be copied");
515template<
typename Function,
typename ResultType,
typename ParentResultType>
528 launchAsync =
f->d.launchAsync();
531 if (launchAsync &&
f->d.threadPool()) {
532 pool =
f->d.threadPool();
537 fi.setLaunchAsync(launchAsync);
546 fi.setRunnable(asyncJob);
547 continuationJob = asyncJob;
550 std::forward<Function>(
func),
parent, std::move(promise));
553 bool isLaunched = continuationJob->
execute();
557 if (!(launchAsync && isLaunched)) {
558 delete continuationJob;
559 continuationJob =
nullptr;
565template<
typename Function,
typename ResultType,
typename ParentResultType>
574 fi.setLaunchAsync(
true);
582 bool isLaunched = continuationJob->execute();
586 delete continuationJob;
587 continuationJob =
nullptr;
593template<
typename Function,
typename ResultType,
typename ParentResultType>
609 std::forward<Function>(
func),
parent, std::move(promise));
616 context, std::move(continuation));
624template<
typename Function,
typename ResultType,
typename ParentResultType>
627 if constexpr (std::is_copy_constructible_v<ParentResultType>)
633template<
typename Function,
typename ResultType,
typename ParentResultType>
634void Continuation<Function, ResultType, ParentResultType>::fulfillVoidPromise()
636 if constexpr (std::is_copy_constructible_v<ParentResultType>)
639 function(parentFuture.takeResult());
642template<
typename Function,
typename ResultType,
typename ParentResultType>
643void Continuation<Function, ResultType, ParentResultType>::fulfillPromiseWithVoidResult()
645 if constexpr (std::is_invocable_v<Function, QFuture<void>>)
651template<
typename Function,
typename ResultType,
typename ParentResultType>
652template<
class... Args>
653void Continuation<Function, ResultType, ParentResultType>::fulfillPromise(Args &&...
args)
655 promise.addResult(std::invoke(function, std::forward<Args>(
args)...));
661 if constexpr (!std::is_void_v<T>) {
662 if constexpr (std::is_copy_constructible_v<T>)
669template<
class T,
class Function>
672 if constexpr (std::is_void_v<T>)
678#ifndef QT_NO_EXCEPTIONS
680template<
class Function,
class ResultType>
691 parent, std::move(promise));
692 failureHandler.
run();
698template<
class Function,
class ResultType>
710 failureHandler.
run();
721template<
class Function,
class ResultType>
724 Q_ASSERT(parentFuture.isFinished());
728 if (parentFuture.d.hasException()) {
730 if constexpr (std::is_void_v<ArgType>) {
731 handleAllExceptions();
733 handleException<ArgType>();
735 }
else if (parentFuture.d.isChainCanceled()) {
736 promise.future().cancel();
743template<
class Function,
class ResultType>
744template<
class ArgType>
748 Q_ASSERT(parentFuture.d.hasException());
749 parentFuture.d.exceptionStore().rethrowException();
750 }
catch (
const ArgType &
e) {
753 if constexpr (std::is_void_v<ResultType>)
756 promise.addResult(handler(
e));
758 promise.setException(std::current_exception());
763 promise.setException(std::current_exception());
767template<
class Function,
class ResultType>
768void FailureHandler<Function, ResultType>::handleAllExceptions()
771 Q_ASSERT(parentFuture.d.hasException());
772 parentFuture.d.exceptionStore().rethrowException();
777 promise.setException(std::current_exception());
784template<
class Function,
class ResultType>
788 template<
class F = Function>
793 auto canceledContinuation = [promise =
QPromise(
fi), handler = std::forward<F>(handler)](
796 run(std::forward<F>(handler), parentFuture, std::move(promise));
801 template<
class F = Function>
807 auto canceledContinuation = [handler = std::forward<F>(handler),
809 run(std::forward<F>(handler), parentFuture, std::move(promise));
815 context, std::move(canceledContinuation));
821 template<
class F = Function>
827#ifndef QT_NO_EXCEPTIONS
828 if (parentFuture.d.hasException()) {
830 promise.setException(parentFuture.d.exceptionStore().exception());
835#ifndef QT_NO_EXCEPTIONS
837 promise.setException(std::current_exception());
865#ifndef QT_NO_EXCEPTIONS
866 if (outerFuture.d.hasException()) {
875 ResultType nestedFuture = outerFuture.
result();
878#ifndef QT_NO_EXCEPTIONS
879 if (nested.d.hasException()) {
880 promise.reportException(nested.d.exceptionStore().exception());
884 if constexpr (!std::is_void_v<NestedType>)
885 promise.reportResults(nested.results());
888 }).onCanceled([promise] ()
mutable {
892 }).onCanceled([promise]()
mutable {
902template<
typename ValueType>
916template<
class Signal>
919template<
class Sender,
class Signal,
typename = QtPrivate::EnableIfInvocable<Sender, Signal>>
931 using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
932 auto connections = std::make_shared<Connections>();
934 if constexpr (std::is_void_v<ArgsType>) {
943 [promise, connections](
auto...
values)
mutable {
960 if (!connections->first) {
966 connections->second =
977template<
typename Container>
979 std::enable_if_t<QtPrivate::HasInputIterator<Container>::value,
bool>;
981template<
typename Container>
983 typename std::iterator_traits<
decltype(
984 std::cbegin(std::declval<Container&>()))>::value_type;
986template<
typename Container, if_container_with_input_iterators<Container> = true>
992 if constexpr (std::is_convertible_v<q20::remove_cvref_t<Container>,
QList<ValueType>>) {
996 std::cend(container)});
1000template<
typename ValueType>
1019#if QT_DEPRECATED_SINCE(6, 10)
1020template<
typename T,
typename = QtPrivate::EnableForNonVo
id<T>>
1038#ifndef QT_NO_EXCEPTIONS
1040template<
typename T =
void>
1051template<
typename T =
void>
1057 return makeExceptionalFuture<T>(std::current_exception());
1068template<
typename ResultFutures>
1075 template<
typename T = ValueType>
1081 if (oldRemaining <= 1) {
1092template<
typename ResultType>
1097 template<
typename T = ResultType,
typename = EnableForNonVo
id<T>>
1110template<
qsizetype Index,
typename ContextType,
typename... Ts>
1112 const std::tuple<Ts...> &
t)
1114 auto future = std::get<Index>(
t);
1115 using ResultType =
typename ContextType::ValueType;
1116 future.then([
context](
const std::tuple_element_t<Index, std::tuple<Ts...>> &
f) {
1117 context->checkForCompletion(Index, ResultType { std::in_place_index<Index>,
f });
1119 context->checkForCompletion(Index, ResultType { std::in_place_index<Index>,
future });
1122 if constexpr (Index != 0)
1123 addCompletionHandlersImpl<Index - 1, ContextType, Ts...>(
context,
t);
1126template<
typename ContextType,
typename... Ts>
1133template<
typename OutputSequence,
typename InputIt,
typename ValueType>
1140 const auto context = std::make_shared<QtPrivate::WhenAllContext<OutputSequence>>(
size);
1146 it->then([
context, idx](
const ValueType &
f) {
1147 context->checkForCompletion(idx,
f);
1149 context->checkForCompletion(idx,
f);
1152 return context->promise.future();
1155template<
typename OutputSequence,
typename... Futures>
1159 const auto context = std::make_shared<QtPrivate::WhenAllContext<OutputSequence>>(
size);
1165 return context->promise.future();
1168template<
typename InputIt,
typename ValueType>
1181 const auto context = std::make_shared<QtPrivate::WhenAnyContext<ResultType>>();
1186 it->then([
context, idx](
const ValueType &
f) {
1192 return context->promise.future();
1195template<
typename... Futures>
1198 using ResultType = std::variant<std::decay_t<Futures>...>;
1200 const auto context = std::make_shared<QtPrivate::WhenAnyContext<ResultType>>();
1205 return context->promise.future();
T fetchAndStoreRelaxed(T newValue) noexcept
T fetchAndSubRelaxed(T valueToAdd) noexcept
virtual void raise() const
In your QException subclass, reimplement raise() like this:
bool reportResults(const QList< T > &results, int beginIndex=-1, int count=-1)
void reportException(const std::exception_ptr &e)
bool reportFinished(const T *result)
bool reportResult(const T *result, int index=-1)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void deleteLater()
\threadsafe
bool addResult(U &&result, int index=-1)
void start(QRunnable *runnable, int priority=0)
Reserves a thread and uses it to run runnable, unless this thread will make the current thread count ...
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
~AsyncContinuation() override=default
AsyncContinuation(F &&func, const QFuture< ParentResultType > &f, QPromise< ResultType > &&p, QThreadPool *pool=nullptr)
void run() override
Implement this pure virtual function in your subclass.
static void create(F &&handler, QFuture< ResultType > *future, QFutureInterface< ResultType > &fi, QObject *context)
static void create(F &&handler, QFuture< ResultType > *future, QFutureInterface< ResultType > &fi)
static void run(F &&handler, QFuture< ResultType > &parentFuture, QPromise< ResultType > &&promise)
QFuture< ParentResultType > parentFuture
Continuation(F &&func, const QFuture< ParentResultType > &f, QPromise< ResultType > &&p)
virtual ~Continuation()=default
static void create(F &&func, QFuture< ParentResultType > *f, QFutureInterface< ResultType > &fi, QtFuture::Launch policy)
QPromise< ResultType > promise
static void create(F &&function, QFuture< ResultType > *future, const QFutureInterface< ResultType > &fi)
FailureHandler(F &&func, const QFuture< ResultType > &f, QPromise< ResultType > &&p)
~SyncContinuation() override=default
SyncContinuation(F &&func, const QFuture< ParentResultType > &f, QPromise< ResultType > &&p)
QSet< QString >::iterator it
Combined button and popup list for selecting options.
typename std::iterator_traits< decltype(std::cbegin(std::declval< Container & >()))>::value_type ContainedType
Q_CORE_EXPORT QFuture< void > makeReadyVoidFuture()
static QFuture< std::decay_t< T > > makeReadyValueFuture(T &&value)
static QFuture< T > makeExceptionalFuture(std::exception_ptr exception)
static QFuture< ContainedType< Container > > makeReadyRangeFuture(Container &&container)
typename QtPrivate::ArgResolver< Signal >::AllArgs ArgsType
static QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
std::enable_if_t< QtPrivate::HasInputIterator< Container >::value, bool > if_container_with_input_iterators
QFuture< OutputSequence > whenAllImpl(InputIt first, InputIt last)
std::enable_if_t< QtPrivate::ArgResolver< Callable >::template CanInvokeWithArgs< Class, Callable > > EnableIfInvocable
auto createTuple(Arg &&arg, Args &&... args)
std::bool_constant<(sizeof...(Args) > 0)> NotEmpty
void addCompletionHandlersImpl(const std::shared_ptr< ContextType > &context, const std::tuple< Ts... > &t)
constexpr bool isQFutureV
QFuture< QtFuture::WhenAnyResult< typename Future< ValueType >::type > > whenAnyImpl(InputIt first, InputIt last)
std::is_convertible< typename std::iterator_traits< Iterator >::iterator_category, std::forward_iterator_tag > IsForwardIterable
std::is_convertible< typename std::iterator_traits< std::decay_t< decltype(std::begin(std::declval< Sequence >()))> >::iterator_category, std::random_access_iterator_tag > IsRandomAccessible
std::is_convertible< typename std::iterator_traits< std::decay_t< decltype(std::begin(std::declval< Sequence >()))> >::iterator_category, std::input_iterator_tag > HasInputIterator
std::bool_constant< isQFutureV< T > > isQFuture
void fulfillPromise(QPromise< T > &promise, QFuture< T > &future)
QFuture< ValueType > makeReadyRangeFutureImpl(const QList< ValueType > &values)
std::enable_if_t<!std::is_same_v< T, void > > EnableForNonVoid
constexpr bool IsPrivateSignalArg
std::enable_if_t< std::is_same_v< T, void > > EnableForVoid
auto cutTuple(Tuple &&t, std::index_sequence< I... >)
std::conditional_t< FunctionPointer< std::decay_t< Func > >::ArgumentCount==-1, ZeroArgFunctor< std::decay_t< Func > >, FunctionPointer< std::decay_t< Func > > > Callable
void addCompletionHandlers(const std::shared_ptr< ContextType > &context, const std::tuple< Ts... > &t)
std::conditional_t<(sizeof...(Args) > 0), std::invoke_result_t< decltype(createTuple< Arg, Args... >), Arg, Args... >, std::conditional_t< IsPrivateSignalArg< Arg >, void, Arg > > FilterLastPrivateSignalArg
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLenum GLsizei GLsizei GLint * values
[15]
GLenum GLuint GLintptr GLsizeiptr size
[1]
#define Q_ASSERT_X(cond, x, msg)
#define QT_DEPRECATED_VERSION_X(major, minor, text)
QFuture< void > future
[5]
QFutureWatcher< int > watcher
QFileInfo fi("c:/temp/foo")
[newstuff]
std::false_type IsPromise
FilterLastPrivateSignalArg< std::decay_t< Arg >, std::decay_t< Args >... > AllArgs
FilterLastPrivateSignalArg< QPromise< Arg >, std::decay_t< Args >... > AllArgs
std::false_type IsPromise
void operator()(const QFutureInterfaceBase &parentData)
ContinuationWrapper(ContinuationWrapper &&other)=default
ContinuationWrapper & operator=(ContinuationWrapper &&)=default
ContinuationWrapper(Function &&f)
ContinuationWrapper(const ContinuationWrapper &other)
std::invoke_result_t< std::decay_t< F >, QFuture< Arg > > ResultType
std::invoke_result_t< std::decay_t< F >, std::decay_t< Arg > > ResultType
std::invoke_result_t< std::decay_t< F >, QFuture< void > > ResultType
std::invoke_result_t< std::decay_t< F > > ResultType
static auto unwrapImpl(T *outer)
QAtomicInteger< qsizetype > remaining
QPromise< ResultFutures > promise
WhenAllContext(qsizetype size)
void checkForCompletion(qsizetype index, T &&future)
typename ResultFutures::value_type ValueType
QPromise< ResultType > promise
void checkForCompletion(qsizetype, T &&result)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent