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