1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #ifndef QTHREAD_H
42 #define QTHREAD_H
43
44 #include <QtCore/qobject.h>
45 #include <QtCore/qdeadlinetimer.h>
46
47 // For QThread::create. The configure-time test just checks for the availability
48 // of std::future and std::async; for the C++17 codepath we perform some extra
49 // checks here (for std::invoke and C++14 lambdas).
50 #if QT_CONFIG(cxx11_future)
51 # include <future> // for std::async
52 # include <functional> // for std::invoke; no guard needed as it's a C++98 header
53
54 # if defined(__cpp_lib_invoke) && __cpp_lib_invoke >= 201411 \
55 && defined(__cpp_init_captures) && __cpp_init_captures >= 201304 \
56 && defined(__cpp_generic_lambdas) && __cpp_generic_lambdas >= 201304
57 # define QTHREAD_HAS_VARIADIC_CREATE
58 # endif
59 #endif
60
61 QT_BEGIN_NAMESPACE
62
63
64 class QThreadData;
65 class QThreadPrivate;
66 class QAbstractEventDispatcher;
67
68 class Q_CORE_EXPORT QThread : public QObject
69 {
70 Q_OBJECT
71 public:
72 static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
73 static QThread *currentThread();
74 static int idealThreadCount() noexcept;
75 static void yieldCurrentThread();
76
77 explicit QThread(QObject *parent = nullptr);
78 ~QThread();
79
80 enum Priority {
81 IdlePriority,
82
83 LowestPriority,
84 LowPriority,
85 NormalPriority,
86 HighPriority,
87 HighestPriority,
88
89 TimeCriticalPriority,
90
91 InheritPriority
92 };
93
94 void setPriority(Priority priority);
95 Priority priority() const;
96
97 bool isFinished() const;
98 bool isRunning() const;
99
100 void requestInterruption();
101 bool isInterruptionRequested() const;
102
103 void setStackSize(uint stackSize);
104 uint stackSize() const;
105
106 void exit(int retcode = 0);
107
108 QAbstractEventDispatcher *eventDispatcher() const;
109 void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
110
111 bool event(QEvent *event) override;
112 int loopLevel() const;
113
114 #ifdef Q_CLANG_QDOC
115 template <typename Function, typename... Args>
116 static QThread *create(Function &&f, Args &&... args);
117 template <typename Function>
118 static QThread *create(Function &&f);
119 #else
120 # if QT_CONFIG(cxx11_future)
121 # ifdef QTHREAD_HAS_VARIADIC_CREATE
122 template <typename Function, typename... Args>
123 static QThread *create(Function &&f, Args &&... args);
124 # else
125 template <typename Function>
126 static QThread *create(Function &&f);
127 # endif // QTHREAD_HAS_VARIADIC_CREATE
128 # endif // QT_CONFIG(cxx11_future)
129 #endif // Q_CLANG_QDOC
130
131 public Q_SLOTS:
132 void start(Priority = InheritPriority);
133 void terminate();
134 void quit();
135
136 public:
137 bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever));
138 // ### Qt6 inline this function
139 bool wait(unsigned long time);
140
141 static void sleep(unsigned long);
142 static void msleep(unsigned long);
143 static void usleep(unsigned long);
144
145 Q_SIGNALS:
146 void started(QPrivateSignal);
147 void finished(QPrivateSignal);
148
149 protected:
150 virtual void run();
151 int exec();
152
153 static void setTerminationEnabled(bool enabled = true);
154
155 protected:
156 QThread(QThreadPrivate &dd, QObject *parent = nullptr);
157
158 private:
159 Q_DECLARE_PRIVATE(QThread)
160
161 #if QT_CONFIG(cxx11_future)
162 static QThread *createThreadImpl(std::future<void> &&future);
163 #endif
164
165 friend class QCoreApplication;
166 friend class QThreadData;
167 };
168
169 #if QT_CONFIG(cxx11_future)
170
171 #if defined(QTHREAD_HAS_VARIADIC_CREATE) || defined(Q_CLANG_QDOC)
172 // C++17: std::thread's constructor complying call
173 template <typename Function, typename... Args>
create(Function && f,Args &&...args)174 QThread *QThread::create(Function &&f, Args &&... args)
175 {
176 using DecayedFunction = typename std::decay<Function>::type;
177 auto threadFunction =
178 [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
179 {
180 (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
181 };
182
183 return createThreadImpl(std::async(std::launch::deferred,
184 std::move(threadFunction),
185 std::forward<Args>(args)...));
186 }
187 #elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
188 // C++14: implementation for just one callable
189 template <typename Function>
create(Function && f)190 QThread *QThread::create(Function &&f)
191 {
192 using DecayedFunction = typename std::decay<Function>::type;
193 auto threadFunction =
194 [f = static_cast<DecayedFunction>(std::forward<Function>(f))]() mutable -> void
195 {
196 (void)f();
197 };
198
199 return createThreadImpl(std::async(std::launch::deferred, std::move(threadFunction)));
200 }
201 #else
202 // C++11: same as C++14, but with a workaround for not having generalized lambda captures
203 namespace QtPrivate {
204 template <typename Function>
205 struct Callable
206 {
CallableCallable207 explicit Callable(Function &&f)
208 : m_function(std::forward<Function>(f))
209 {
210 }
211
212 // Apply the same semantics of a lambda closure type w.r.t. the special
213 // member functions, if possible: delete the copy assignment operator,
214 // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
215 ~Callable() = default;
216 Callable(const Callable &) = default;
217 Callable(Callable &&) = default;
218 Callable &operator=(const Callable &) = delete;
219 Callable &operator=(Callable &&) = default;
220
operatorCallable221 void operator()()
222 {
223 (void)m_function();
224 }
225
226 typename std::decay<Function>::type m_function;
227 };
228 } // namespace QtPrivate
229
230 template <typename Function>
create(Function && f)231 QThread *QThread::create(Function &&f)
232 {
233 return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f))));
234 }
235 #endif // QTHREAD_HAS_VARIADIC_CREATE
236
237 #endif // QT_CONFIG(cxx11_future)
238
239 QT_END_NAMESPACE
240
241 #endif // QTHREAD_H
242