Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-02 10:02:59

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