File indexing completed on 2024-05-12 17:08:32

0001 /*
0002  *   SPDX-FileCopyrightText: 2017 Ivan Čukić <ivan.cukic(at)kde.org>
0003  *
0004  *   SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 
0007 //
0008 // W A R N I N G
0009 // -------------
0010 //
0011 // This file is not part of the AsynQt API. It exists purely as an
0012 // implementation detail. This header file may change from version to
0013 // version without notice, or even be removed.
0014 //
0015 // We mean it.
0016 //
0017 
0018 #include "../utils_p.h"
0019 
0020 namespace AsynQt
0021 {
0022 namespace detail
0023 {
0024 template<typename T>
0025 struct isNullary {
0026 private:
0027     template<typename U>
0028     static decltype(std::declval<U>()(), std::true_type()) test(int);
0029 
0030     template<typename>
0031     static std::false_type test(...);
0032 
0033 public:
0034     typedef decltype(test<T>(0)) type;
0035     enum { value = type::value };
0036 };
0037 
0038 template<typename _Function>
0039 class PassResult
0040 {
0041 private:
0042     using isNullaryFunction = typename isNullary<_Function>::type;
0043     _Function m_function;
0044 
0045     template<typename _Result>
0046     void callFunction(const QFuture<_Result> &future, std::true_type) const
0047     {
0048         Q_UNUSED(future);
0049         if (!future.isCanceled()) {
0050             m_function();
0051         }
0052     }
0053 
0054     template<typename _Result>
0055     void callFunction(const QFuture<_Result> &future, std::false_type) const
0056     {
0057         if (future.resultCount()) {
0058             m_function(future.result());
0059         }
0060     }
0061 
0062 public:
0063     PassResult(_Function function)
0064         : m_function(function)
0065     {
0066     }
0067 
0068     template<typename _Result>
0069     void operator()(const QFuture<_Result> &future) const
0070     {
0071         callFunction(future, isNullaryFunction());
0072     }
0073 };
0074 
0075 template<typename _Function>
0076 class PassError
0077 {
0078 public:
0079     PassError(_Function function)
0080         : m_function(function)
0081     {
0082     }
0083 
0084     template<typename _Result>
0085     void operator()(const QFuture<_Result> &future) const
0086     {
0087         if (future.isCanceled()) {
0088             m_function();
0089         }
0090     }
0091 
0092 private:
0093     _Function m_function;
0094 };
0095 
0096 template<typename _Type, typename _Function>
0097 QFuture<_Type> onFinished_impl(const QFuture<_Type> &future, _Function &&function)
0098 {
0099     auto watcher = new QFutureWatcher<_Type>();
0100     QObject::connect(watcher, &QFutureWatcherBase::finished, [watcher, function]() {
0101         function(watcher->future());
0102         watcher->deleteLater();
0103     });
0104     watcher->setFuture(future);
0105 
0106     return future;
0107 }
0108 
0109 namespace operators
0110 {
0111 template<typename _Function>
0112 class OnFinishedModifier
0113 {
0114 public:
0115     OnFinishedModifier(_Function function)
0116         : m_function(function)
0117     {
0118     }
0119 
0120     _Function m_function;
0121 };
0122 
0123 template<typename _Type, typename _Function>
0124 auto operator|(const QFuture<_Type> &future, OnFinishedModifier<_Function> &&modifier) -> decltype(onFinished_impl(future, modifier.m_function))
0125 {
0126     return onFinished_impl(future, modifier.m_function);
0127 }
0128 
0129 } // namespace operators
0130 
0131 } // namespace detail
0132 } // namespace AsynQt