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
qtconcurrentthreadengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
6
7#if !defined(QT_NO_CONCURRENT) || defined(Q_QDOC)
8
10
11namespace QtConcurrent {
12
13/*!
14 \class QtConcurrent::ThreadEngineBarrier
15 \inmodule QtConcurrent
16 \internal
17*/
18
19/*!
20 \enum QtConcurrent::ThreadFunctionResult
21 \internal
22*/
23
24/*!
25 \class QtConcurrent::ThreadEngineBase
26 \inmodule QtConcurrent
27 \internal
28*/
29
30/*!
31 \class QtConcurrent::ThreadEngine
32 \inmodule QtConcurrent
33 \internal
34*/
35
36/*!
37 \class QtConcurrent::ThreadEngineStarterBase
38 \inmodule QtConcurrent
39 \internal
40*/
41
42/*!
43 \class QtConcurrent::ThreadEngineStarter
44 \inmodule QtConcurrent
45 \internal
46*/
47
48/*!
49 \fn [qtconcurrentthreadengine-1] template <typename ThreadEngine> ThreadEngineStarter<typename ThreadEngine::ResultType> QtConcurrent::startThreadEngine(ThreadEngine *threadEngine)
50 \internal
51*/
52
55
57{
58 forever {
59 int localCount = count.loadRelaxed();
60 if (localCount < 0) {
61 if (count.testAndSetOrdered(localCount, localCount -1))
62 return;
63 } else {
64 if (count.testAndSetOrdered(localCount, localCount + 1))
65 return;
66 }
67 qYieldCpu();
68 }
69}
70
72{
73 forever {
74 int localCount = count.loadRelaxed();
75 if (localCount == -1) {
76 if (count.testAndSetOrdered(-1, 0)) {
77 semaphore.release();
78 return 0;
79 }
80 } else if (localCount < 0) {
81 if (count.testAndSetOrdered(localCount, localCount + 1))
82 return qAbs(localCount + 1);
83 } else {
84 if (count.testAndSetOrdered(localCount, localCount - 1))
85 return localCount - 1;
86 }
87 qYieldCpu();
88 }
89}
90
91// Wait until all threads have been released
93{
94 forever {
95 int localCount = count.loadRelaxed();
96 if (localCount == 0)
97 return;
98
99 Q_ASSERT(localCount > 0); // multiple waiters are not allowed.
100 if (count.testAndSetOrdered(localCount, -localCount)) {
101 semaphore.acquire();
102 return;
103 }
104 qYieldCpu();
105 }
106}
107
109{
110 return count.loadRelaxed();
111}
112
113// releases a thread, unless this is the last thread.
114// returns true if the thread was released.
116{
117 forever {
118 int localCount = count.loadRelaxed();
119 if (qAbs(localCount) == 1) {
120 return false;
121 } else if (localCount < 0) {
122 if (count.testAndSetOrdered(localCount, localCount + 1))
123 return true;
124 } else {
125 if (count.testAndSetOrdered(localCount, localCount - 1))
126 return true;
127 }
128 qYieldCpu();
129 }
130}
131
138
140
142{
143 start();
144 while (threadFunction() != ThreadFinished)
145 ;
146 finish();
147}
148
153
158
164
166{
167 if (futureInterface)
168 return futureInterface->isCanceled();
169 else
170 return false;
171}
172
178
180{
181 // If we don't have a QFuture, there is no-one to report the progress to.
182 return (futureInterface != nullptr);
183}
184
190
196
198{
199 if (this->isCanceled())
200 return false;
201
203 if (!threadPool->tryStart(this)) {
205 return false;
206 }
207 return true;
208}
209
211{
213 ;
214}
215
217{
218 const bool asynchronous = (futureInterface != nullptr);
219 const int lastThread = (barrier.release() == 0);
220
222 this->asynchronousFinish();
223}
224
225// Called by a worker thread that wants to be throttled. If the current number
226// of running threads is larger than one the thread is allowed to exit and
227// this function returns one.
229{
230 return barrier.releaseUnlessLast();
231}
232
233void ThreadEngineBase::run() // implements QRunnable.
234{
235 if (this->isCanceled()) {
236 threadExit();
237 return;
238 }
239
240 startThreads();
241
242#ifndef QT_NO_EXCEPTIONS
243 try {
244#endif
245 while (threadFunction() == ThrottleThread) {
246 // threadFunction returning ThrottleThread means it that the user
247 // struct wants to be throttled by making a worker thread exit.
248 // Respect that request unless this is the only worker thread left
249 // running, in which case it has to keep going.
250 if (threadThrottleExit()) {
251 return;
252 } else {
253 // If the last worker thread is throttled and the state is "suspending",
254 // it means that suspension has been requested, and it is already
255 // in effect (because all previous threads have already exited).
256 // Report the "Suspended" state.
258 }
259 }
260
261#ifndef QT_NO_EXCEPTIONS
262 } catch (QException &e) {
264 } catch (...) {
266 }
267#endif
268 threadExit();
269}
270
271#ifndef QT_NO_EXCEPTIONS
272
274{
275 if (futureInterface) {
277 } else {
281 }
282}
283#endif
284
285
286} // namespace QtConcurrent
287
288QT_END_NAMESPACE
289
290#endif // QT_NO_CONCURRENT
Combined button and popup list for selecting options.
\inmodule QtConcurrent