Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qrunnable.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2023 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 QRUNNABLE_H
0005 #define QRUNNABLE_H
0006 
0007 #include <QtCore/qcompilerdetection.h>
0008 #include <QtCore/qfunctionaltools_impl.h>
0009 #include <QtCore/qtclasshelpermacros.h>
0010 #include <QtCore/qtcoreexports.h>
0011 
0012 #include <functional>
0013 #include <type_traits>
0014 
0015 QT_BEGIN_NAMESPACE
0016 
0017 class Q_CORE_EXPORT QRunnable
0018 {
0019     bool m_autoDelete = true;
0020 
0021     Q_DISABLE_COPY(QRunnable)
0022 public:
0023     virtual void run() = 0;
0024 
0025     constexpr QRunnable() noexcept = default;
0026     virtual ~QRunnable();
0027 #if QT_CORE_REMOVED_SINCE(6, 6)
0028     static QRunnable *create(std::function<void()> functionToRun);
0029 #endif
0030     template <typename Callable>
0031     using if_callable = std::enable_if_t<std::is_invocable_r_v<void, Callable>, bool>;
0032 
0033     template <typename Callable, if_callable<Callable> = true>
0034     static QRunnable *create(Callable &&functionToRun);
0035     static QRunnable *create(std::nullptr_t) = delete;
0036 
0037     bool autoDelete() const { return m_autoDelete; }
0038     void setAutoDelete(bool autoDelete) { m_autoDelete = autoDelete; }
0039 
0040 private:
0041     static Q_DECL_COLD_FUNCTION QRunnable *warnNullCallable();
0042     class QGenericRunnable;
0043 };
0044 
0045 class Q_CORE_EXPORT QRunnable::QGenericRunnable : public QRunnable
0046 {
0047     // Type erasure, to only instantiate a non-virtual class per Callable:
0048     class HelperBase
0049     {
0050     protected:
0051         enum class Op {
0052             Run,
0053             Destroy,
0054         };
0055         using OpFn = void* (*)(Op, HelperBase *, void*);
0056         OpFn fn;
0057     protected:
0058         constexpr explicit HelperBase(OpFn f) noexcept : fn(f) {}
0059         ~HelperBase() = default;
0060     public:
0061         void run() { fn(Op::Run, this, nullptr); }
0062         void destroy() { fn(Op::Destroy, this, nullptr); }
0063     };
0064 
0065     template <typename Callable>
0066     class Helper : public HelperBase, private QtPrivate::CompactStorage<Callable>
0067     {
0068         using Storage = QtPrivate::CompactStorage<Callable>;
0069         static void *impl(Op op, HelperBase *that, [[maybe_unused]] void *arg)
0070         {
0071             const auto _this = static_cast<Helper*>(that);
0072             switch (op) {
0073             case Op::Run:     _this->object()(); break;
0074             case Op::Destroy: delete _this; break;
0075             }
0076             return nullptr;
0077         }
0078     public:
0079         template <typename UniCallable>
0080         explicit Helper(UniCallable &&functionToRun) noexcept
0081             : HelperBase(&impl),
0082               Storage{std::forward<UniCallable>(functionToRun)}
0083         {
0084         }
0085     };
0086 
0087     HelperBase *runHelper;
0088 public:
0089     template <typename Callable, if_callable<Callable> = true>
0090     explicit QGenericRunnable(Callable &&c)
0091         : runHelper(new Helper<std::decay_t<Callable>>(std::forward<Callable>(c)))
0092     {
0093     }
0094     ~QGenericRunnable() override;
0095 
0096     void run() override;
0097 };
0098 
0099 namespace QtPrivate {
0100 
0101 template <typename T>
0102 constexpr inline bool is_function_pointer_v = std::conjunction_v<
0103         std::is_pointer<T>,
0104         std::is_function<std::remove_pointer_t<T>>
0105     >;
0106 template <typename T>
0107 constexpr inline bool is_std_function_v = false;
0108 template <typename T>
0109 constexpr inline bool is_std_function_v<std::function<T>> = true;
0110 
0111 } // namespace QtPrivate
0112 
0113 template <typename Callable, QRunnable::if_callable<Callable>>
0114 QRunnable *QRunnable::create(Callable &&functionToRun)
0115 {
0116     using F = std::decay_t<Callable>;
0117     constexpr bool is_std_function = QtPrivate::is_std_function_v<F>;
0118     constexpr bool is_function_pointer = QtPrivate::is_function_pointer_v<F>;
0119     if constexpr (is_std_function || is_function_pointer) {
0120         bool is_null;
0121         if constexpr (is_std_function) {
0122             is_null = !functionToRun;
0123         } else if constexpr (is_function_pointer) {
0124             // shut up warnings about functions always having a non-null address:
0125             const void *functionPtr = reinterpret_cast<void *>(functionToRun);
0126             is_null = !functionPtr;
0127         }
0128         if (is_null)
0129             return warnNullCallable();
0130     }
0131 
0132     return new QGenericRunnable(std::forward<Callable>(functionToRun));
0133 }
0134 
0135 QT_END_NAMESPACE
0136 
0137 #endif