File indexing completed on 2026-09-09 09:19:54
0001
0002
0003
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
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 }
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
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