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
46// For QThread::create. The configure-time test just checks for the availability
47// of std::future and std::async; for the C++17 codepath we perform some extra
48// checks here (for std::invoke and C++14 lambdas).
49#if QT_CONFIG(cxx11_future)
50# include <future> // for std::async
51# include <functional> // for std::invoke; no guard needed as it's a C++98 header
52
53# if defined(__cpp_lib_invoke) && __cpp_lib_invoke >= 201411 \
54 && defined(__cpp_init_captures) && __cpp_init_captures >= 201304 \
55 && defined(__cpp_generic_lambdas) && __cpp_generic_lambdas >= 201304
56# define QTHREAD_HAS_VARIADIC_CREATE
57# endif
58#endif
59
60#include <limits.h>
61
62QT_BEGIN_NAMESPACE
63
64
65class QThreadData;
66class QThreadPrivate;
67class QAbstractEventDispatcher;
68
69class Q_CORE_EXPORT QThread : public QObject
70{
71 Q_OBJECT
72public:
73 static Qt::HANDLE currentThreadId() Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
74 static QThread *currentThread();
75 static int idealThreadCount() Q_DECL_NOTHROW;
76 static void yieldCurrentThread();
77
78 explicit QThread(QObject *parent = nullptr);
79 ~QThread();
80
81 enum Priority {
82 IdlePriority,
83
84 LowestPriority,
85 LowPriority,
86 NormalPriority,
87 HighPriority,
88 HighestPriority,
89
90 TimeCriticalPriority,
91
92 InheritPriority
93 };
94
95 void setPriority(Priority priority);
96 Priority priority() const;
97
98 bool isFinished() const;
99 bool isRunning() const;
100
101 void requestInterruption();
102 bool isInterruptionRequested() const;
103
104 void setStackSize(uint stackSize);
105 uint stackSize() const;
106
107 void exit(int retcode = 0);
108
109 QAbstractEventDispatcher *eventDispatcher() const;
110 void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
111
112 bool event(QEvent *event) override;
113 int loopLevel() const;
114
115#ifdef Q_CLANG_QDOC
116 template <typename Function, typename... Args>
117 static QThread *create(Function &&f, Args &&... args);
118 template <typename Function>
119 static QThread *create(Function &&f);
120#else
121# if QT_CONFIG(cxx11_future)
122# ifdef QTHREAD_HAS_VARIADIC_CREATE
123 template <typename Function, typename... Args>
124 static QThread *create(Function &&f, Args &&... args);
125# else
126 template <typename Function>
127 static QThread *create(Function &&f);
128# endif // QTHREAD_HAS_VARIADIC_CREATE
129# endif // QT_CONFIG(cxx11_future)
130#endif // Q_CLANG_QDOC
131
132public Q_SLOTS:
133 void start(Priority = InheritPriority);
134 void terminate();
135 void quit();
136
137public:
138 // default argument causes thread to block indefinetely
139 bool wait(unsigned long time = ULONG_MAX);
140
141 static void sleep(unsigned long);
142 static void msleep(unsigned long);
143 static void usleep(unsigned long);
144
145Q_SIGNALS:
146 void started(QPrivateSignal);
147 void finished(QPrivateSignal);
148
149protected:
150 virtual void run();
151 int exec();
152
153 static void setTerminationEnabled(bool enabled = true);
154
155protected:
156 QThread(QThreadPrivate &dd, QObject *parent = nullptr);
157
158private:
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
173template <typename Function, typename... Args>
174QThread *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
189template <typename Function>
190QThread *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
203namespace QtPrivate {
204template <typename Function>
205struct Callable
206{
207 explicit Callable(Function &&f)
208 : m_function(std::forward<Function>(f))
209 {
210 }
211
212#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
213 // Apply the same semantics of a lambda closure type w.r.t. the special
214 // member functions, if possible: delete the copy assignment operator,
215 // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
216 ~Callable() = default;
217 Callable(const Callable &) = default;
218 Callable(Callable &&) = default;
219 Callable &operator=(const Callable &) = delete;
220 Callable &operator=(Callable &&) = default;
221#endif
222
223 void operator()()
224 {
225 (void)m_function();
226 }
227
228 typename std::decay<Function>::type m_function;
229};
230} // namespace QtPrivate
231
232template <typename Function>
233QThread *QThread::create(Function &&f)
234{
235 return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f))));
236}
237#endif // QTHREAD_HAS_VARIADIC_CREATE
238
239#endif // QT_CONFIG(cxx11_future)
240
241QT_END_NAMESPACE
242
243#endif // QTHREAD_H
244