Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:09:51

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QTCONCURRENT_STOREDFUNCTIONCALL_H
0005 #define QTCONCURRENT_STOREDFUNCTIONCALL_H
0006 
0007 #include <QtConcurrent/qtconcurrent_global.h>
0008 
0009 #ifndef QT_NO_CONCURRENT
0010 #include <QtConcurrent/qtconcurrentrunbase.h>
0011 #include <QtCore/qpromise.h>
0012 
0013 #include <type_traits>
0014 
0015 QT_BEGIN_NAMESPACE
0016 
0017 #ifndef Q_QDOC
0018 
0019 namespace QtConcurrent {
0020 
0021 template<typename...>
0022 struct NonMemberFunctionResolver;
0023 
0024 template <class Function, class PromiseType, class... Args>
0025 struct NonMemberFunctionResolver<Function, PromiseType, Args...>
0026 {
0027     using Type = std::tuple<std::decay_t<Function>, QPromise<PromiseType> &, std::decay_t<Args>...>;
0028     static_assert(std::is_invocable_v<std::decay_t<Function>, QPromise<PromiseType> &, std::decay_t<Args>...>,
0029                   "It's not possible to invoke the function with passed arguments.");
0030     static_assert(std::is_void_v<std::invoke_result_t<std::decay_t<Function>, QPromise<PromiseType> &, std::decay_t<Args>...>>,
0031                   "The function must return void type.");
0032 
0033     static constexpr void invoke(std::decay_t<Function> function, QPromise<PromiseType> &promise,
0034                                  std::decay_t<Args>... args)
0035     {
0036         std::invoke(function, promise, args...);
0037     }
0038     static Type initData(Function &&f, QPromise<PromiseType> &promise, Args &&...args)
0039     {
0040         return Type { std::forward<Function>(f), std::ref(promise), std::forward<Args>(args)... };
0041     }
0042 };
0043 
0044 template<typename...>
0045 struct MemberFunctionResolver;
0046 
0047 template <typename Function, typename PromiseType, typename Arg, typename ... Args>
0048 struct MemberFunctionResolver<Function, PromiseType, Arg, Args...>
0049 {
0050     using Type = std::tuple<std::decay_t<Function>, std::decay_t<Arg>, QPromise<PromiseType> &, std::decay_t<Args>...>;
0051     static_assert(std::is_invocable_v<std::decay_t<Function>, std::decay_t<Arg>, QPromise<PromiseType> &, std::decay_t<Args>...>,
0052                   "It's not possible to invoke the function with passed arguments.");
0053     static_assert(std::is_void_v<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Arg>, QPromise<PromiseType> &, std::decay_t<Args>...>>,
0054                   "The function must return void type.");
0055 
0056     static constexpr void invoke(std::decay_t<Function> function, std::decay_t<Arg> object,
0057                                  QPromise<PromiseType> &promise, std::decay_t<Args>... args)
0058     {
0059         std::invoke(function, object, promise, args...);
0060     }
0061     static Type initData(Function &&f, QPromise<PromiseType> &promise, Arg &&fa, Args &&...args)
0062     {
0063         return Type { std::forward<Function>(f), std::forward<Arg>(fa), std::ref(promise), std::forward<Args>(args)... };
0064     }
0065 };
0066 
0067 template <class IsMember, class Function, class PromiseType, class... Args>
0068 struct FunctionResolverHelper;
0069 
0070 template <class Function, class PromiseType, class... Args>
0071 struct FunctionResolverHelper<std::false_type, Function, PromiseType, Args...>
0072         : public NonMemberFunctionResolver<Function, PromiseType, Args...>
0073 {
0074 };
0075 
0076 template <class Function, class PromiseType, class... Args>
0077 struct FunctionResolverHelper<std::true_type, Function, PromiseType, Args...>
0078         : public MemberFunctionResolver<Function, PromiseType, Args...>
0079 {
0080 };
0081 
0082 template <class Function, class PromiseType, class... Args>
0083 struct FunctionResolver
0084         : public FunctionResolverHelper<typename std::is_member_function_pointer<
0085                  std::decay_t<Function>>::type, Function, PromiseType, Args...>
0086 {
0087 };
0088 
0089 template <class Function, class ...Args>
0090 struct InvokeResult
0091 {
0092     static_assert(std::is_invocable_v<std::decay_t<Function>, std::decay_t<Args>...>,
0093                   "It's not possible to invoke the function with passed arguments.");
0094 
0095     using Type = std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>;
0096 };
0097 
0098 template <class Function, class ...Args>
0099 using InvokeResultType = typename InvokeResult<Function, Args...>::Type;
0100 
0101 template <class ...Types>
0102 using DecayedTuple = std::tuple<std::decay_t<Types>...>;
0103 
0104 template <class Function, class ...Args>
0105 struct StoredFunctionCall : public RunFunctionTaskBase<InvokeResultType<Function, Args...>>
0106 {
0107     StoredFunctionCall(DecayedTuple<Function, Args...> &&_data)
0108         : data(std::move(_data))
0109     {}
0110 
0111 protected:
0112     void runFunctor() override
0113     {
0114         constexpr auto invoke = [] (std::decay_t<Function> function,
0115                                     std::decay_t<Args>... args) -> auto {
0116             return std::invoke(function, args...);
0117         };
0118 
0119         if constexpr (std::is_void_v<InvokeResultType<Function, Args...>>) {
0120             std::apply(invoke, std::move(data));
0121         } else {
0122             auto result = std::apply(invoke, std::move(data));
0123 
0124             using T = InvokeResultType<Function, Args...>;
0125             if constexpr (std::is_move_constructible_v<T>)
0126                 this->promise.reportAndMoveResult(std::move(result));
0127             else if constexpr (std::is_copy_constructible_v<T>)
0128                 this->promise.reportResult(result);
0129         }
0130     }
0131 
0132 private:
0133     DecayedTuple<Function, Args...> data;
0134 };
0135 
0136 template <class Function, class PromiseType, class ...Args>
0137 struct StoredFunctionCallWithPromise : public RunFunctionTaskBase<PromiseType>
0138 {
0139     using Resolver = FunctionResolver<Function, PromiseType, Args...>;
0140     using DataType = typename Resolver::Type;
0141     StoredFunctionCallWithPromise(Function &&f, Args &&...args)
0142         : prom(this->promise),
0143           data(std::move(Resolver::initData(std::forward<Function>(f), std::ref(prom),
0144                                             std::forward<Args>(args)...)))
0145     {}
0146 
0147     StoredFunctionCallWithPromise(DecayedTuple<Function, Args...> &&_data)
0148         : StoredFunctionCallWithPromise(std::move(_data),
0149                std::index_sequence_for<std::decay_t<Function>, std::decay_t<Args>...>())
0150     {}
0151 
0152 protected:
0153     void runFunctor() override
0154     {
0155         std::apply(Resolver::invoke, std::move(data));
0156     }
0157 
0158 private:
0159     // helper to pack back the tuple into parameter pack
0160     template<std::size_t... Is>
0161     StoredFunctionCallWithPromise(DecayedTuple<Function, Args...> &&_data,
0162                                   std::index_sequence<Is...>)
0163         : StoredFunctionCallWithPromise(std::move(std::get<Is>(_data))...)
0164     {}
0165 
0166     QPromise<PromiseType> prom;
0167     DataType data;
0168 };
0169 
0170 template<typename...>
0171 struct NonPromiseTaskResolver;
0172 
0173 template <typename Function, typename ... Args>
0174 struct NonPromiseTaskResolver<Function, Args...>
0175 {
0176     using TaskWithArgs = DecayedTuple<Function, Args...>;
0177     static auto run(TaskWithArgs &&args, const TaskStartParameters &startParameters) {
0178         return (new StoredFunctionCall<Function, Args...>(std::move(args)))
0179                 ->start(startParameters);
0180     }
0181 };
0182 
0183 template<typename...>
0184 struct PromiseTaskResolver;
0185 
0186 template <typename Function, typename ... Args>
0187 struct PromiseTaskResolver<Function, Args...>
0188 {
0189     static_assert(QtPrivate::ArgResolver<Function>::IsPromise::value,
0190         "The first argument of passed callable object isn't a QPromise<T> & type. "
0191         "Did you intend to pass a callable which takes a QPromise<T> & type as a first argument? "
0192         "Otherwise it's not possible to invoke the function with passed arguments.");
0193     using TaskWithArgs = DecayedTuple<Function, Args...>;
0194     static auto run(TaskWithArgs &&args, const TaskStartParameters &startParameters) {
0195         using PromiseType = typename QtPrivate::ArgResolver<Function>::PromiseType;
0196         return (new StoredFunctionCallWithPromise<Function, PromiseType, Args...>(std::move(args)))
0197                    ->start(startParameters);
0198     }
0199 };
0200 
0201 template <class IsDirectlyInvocable, class Function, class... Args>
0202 struct TaskResolverHelper;
0203 
0204 template <class Function, class... Args>
0205 struct TaskResolverHelper<std::true_type, Function, Args...>
0206         : public NonPromiseTaskResolver<Function, Args...>
0207 {
0208 };
0209 
0210 template <class Function, class... Args>
0211 struct TaskResolverHelper<std::false_type, Function, Args...>
0212         : public PromiseTaskResolver<Function, Args...>
0213 {
0214 };
0215 
0216 template <class Function, class... Args>
0217 struct TaskResolver : public TaskResolverHelper<typename std::is_invocable<std::decay_t<Function>,
0218         std::decay_t<Args>...>::type, Function, Args...>
0219 {
0220 };
0221 
0222 } //namespace QtConcurrent
0223 
0224 #endif // Q_QDOC
0225 
0226 QT_END_NAMESPACE
0227 
0228 #endif // QT_NO_CONCURRENT
0229 
0230 #endif