Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-09 09:19:54

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