Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qrunnable.h
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QRUNNABLE_H
6#define QRUNNABLE_H
7
8#include <QtCore/qcompilerdetection.h>
9#include <QtCore/qfunctionaltools_impl.h>
10#include <QtCore/qtclasshelpermacros.h>
11#include <QtCore/qtcoreexports.h>
12
13#include <functional>
14#include <type_traits>
15
17
19{
20 bool m_autoDelete = true;
21
22 Q_DISABLE_COPY(QRunnable)
23public:
24 virtual void run() = 0;
25
26 constexpr QRunnable() noexcept = default;
27 virtual ~QRunnable();
28#if QT_CORE_REMOVED_SINCE(6, 6)
29 static QRunnable *create(std::function<void()> functionToRun);
30#endif
31 template <typename Callable>
32 using if_callable = std::enable_if_t<std::is_invocable_r_v<void, Callable>, bool>;
33
34 template <typename Callable, if_callable<Callable> = true>
35 static QRunnable *create(Callable &&functionToRun);
36 static QRunnable *create(std::nullptr_t) = delete;
37
38 bool autoDelete() const { return m_autoDelete; }
39 void setAutoDelete(bool autoDelete) { m_autoDelete = autoDelete; }
40
41private:
42 static Q_DECL_COLD_FUNCTION QRunnable *warnNullCallable();
43 class QGenericRunnable;
44};
45
46class Q_CORE_EXPORT QRunnable::QGenericRunnable : public QRunnable
47{
48 // Type erasure, to only instantiate a non-virtual class per Callable:
49 class HelperBase
50 {
51 protected:
52 enum class Op {
53 Run,
54 Destroy,
55 };
56 using OpFn = void* (*)(Op, HelperBase *, void*);
57 OpFn fn;
58 protected:
59 constexpr explicit HelperBase(OpFn f) noexcept : fn(f) {}
60 ~HelperBase() = default;
61 public:
62 void run() { fn(Op::Run, this, nullptr); }
63 void destroy() { fn(Op::Destroy, this, nullptr); }
64 };
65
66 template <typename Callable>
67 class Helper : public HelperBase, private QtPrivate::CompactStorage<Callable>
68 {
69 using Storage = QtPrivate::CompactStorage<Callable>;
70 static void *impl(Op op, HelperBase *that, [[maybe_unused]] void *arg)
71 {
72 const auto _this = static_cast<Helper*>(that);
73 switch (op) {
74 case Op::Run: _this->object()(); break;
75 case Op::Destroy: delete _this; break;
76 }
77 return nullptr;
78 }
79 public:
80 template <typename UniCallable>
81 explicit Helper(UniCallable &&functionToRun) noexcept
82 : HelperBase(&impl),
83 Storage{std::forward<UniCallable>(functionToRun)}
84 {
85 }
86 };
87
88 HelperBase *runHelper;
89public:
90 template <typename Callable, if_callable<Callable> = true>
91 explicit QGenericRunnable(Callable &&c)
92 : runHelper(new Helper<std::decay_t<Callable>>(std::forward<Callable>(c)))
93 {
94 }
95 ~QGenericRunnable() override;
96
97 void run() override;
98};
99
100namespace QtPrivate {
101
102template <typename T>
103constexpr inline bool is_function_pointer_v = std::conjunction_v<
104 std::is_pointer<T>,
106 >;
107template <typename T>
108constexpr inline bool is_std_function_v = false;
109template <typename T>
110constexpr inline bool is_std_function_v<std::function<T>> = true;
111
112} // namespace QtPrivate
113
114template <typename Callable, QRunnable::if_callable<Callable>>
115QRunnable *QRunnable::create(Callable &&functionToRun)
116{
117 using F = std::decay_t<Callable>;
118 constexpr bool is_std_function = QtPrivate::is_std_function_v<F>;
119 constexpr bool is_function_pointer = QtPrivate::is_function_pointer_v<F>;
120 if constexpr (is_std_function || is_function_pointer) {
121 bool is_null;
122 if constexpr (is_std_function) {
123 is_null = !functionToRun;
124 } else if constexpr (is_function_pointer) {
125 // shut up warnings about functions always having a non-null address:
126 const void *functionPtr = reinterpret_cast<void *>(functionToRun);
127 is_null = !functionPtr;
128 }
129 if (is_null)
130 return warnNullCallable();
131 }
132
133 return new QGenericRunnable(std::forward<Callable>(functionToRun));
134}
135
136QT_END_NAMESPACE
137
138#endif
\inmodule QtCore
Definition qrunnable.h:19
constexpr bool is_std_function_v< std::function< T > >
Definition qrunnable.h:110
constexpr bool is_std_function_v
Definition qrunnable.h:108
constexpr bool is_function_pointer_v
Definition qrunnable.h:103