Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
5
#
include
"qtconcurrentthreadengine.h"
6
7
#
if
!
defined
(
QT_NO_CONCURRENT
)
||
defined
(
Q_QDOC
)
8
9
QT_BEGIN_NAMESPACE
10
11
namespace
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
53
ThreadEngineBarrier
::
ThreadEngineBarrier
()
54
:
count
(0) { }
55
56
void
ThreadEngineBarrier
::
acquire
()
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
71
int
ThreadEngineBarrier
::
release
()
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
92
void
ThreadEngineBarrier
::
wait
()
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
108
int
ThreadEngineBarrier
::
currentCount
()
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.
115
bool
ThreadEngineBarrier
::
releaseUnlessLast
()
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
132
ThreadEngineBase
::
ThreadEngineBase
(
QThreadPool
*
pool
)
133
:
futureInterface
(
nullptr
),
threadPool
(
pool
)
134
{
135
Q_PRE
(
pool
);
136
setAutoDelete
(
false
);
137
}
138
139
ThreadEngineBase
::~
ThreadEngineBase
() {}
140
141
void
ThreadEngineBase
::
startSingleThreaded
()
142
{
143
start
();
144
while
(
threadFunction
() !=
ThreadFinished
)
145
;
146
finish
();
147
}
148
149
void
ThreadEngineBase
::
startThread
()
150
{
151
startThreadInternal
();
152
}
153
154
void
ThreadEngineBase
::
acquireBarrierSemaphore
()
155
{
156
barrier
.
acquire
();
157
}
158
159
void
ThreadEngineBase
::
reportIfSuspensionDone
()
const
160
{
161
if
(
futureInterface
&&
futureInterface
->
isSuspending
())
162
futureInterface
->
reportSuspended
();
163
}
164
165
bool
ThreadEngineBase
::
isCanceled
()
166
{
167
if
(
futureInterface
)
168
return
futureInterface
->
isCanceled
();
169
else
170
return
false
;
171
}
172
173
void
ThreadEngineBase
::
waitForResume
()
174
{
175
if
(
futureInterface
)
176
futureInterface
->
waitForResume
();
177
}
178
179
bool
ThreadEngineBase
::
isProgressReportingEnabled
()
180
{
181
// If we don't have a QFuture, there is no-one to report the progress to.
182
return
(
futureInterface
!=
nullptr
);
183
}
184
185
void
ThreadEngineBase
::
setProgressValue
(
int
progress
)
186
{
187
if
(
futureInterface
)
188
futureInterface
->
setProgressValue
(
progress
);
189
}
190
191
void
ThreadEngineBase
::
setProgressRange
(
int
minimum
,
int
maximum
)
192
{
193
if
(
futureInterface
)
194
futureInterface
->
setProgressRange
(
minimum
,
maximum
);
195
}
196
197
bool
ThreadEngineBase
::
startThreadInternal
()
198
{
199
if
(
this
->
isCanceled
())
200
return
false
;
201
202
barrier
.
acquire
();
203
if
(!
threadPool
->
tryStart
(
this
)) {
204
barrier
.
release
();
205
return
false
;
206
}
207
return
true
;
208
}
209
210
void
ThreadEngineBase
::
startThreads
()
211
{
212
while
(
shouldStartThread
() &&
startThreadInternal
())
213
;
214
}
215
216
void
ThreadEngineBase
::
threadExit
()
217
{
218
const
bool
asynchronous
= (
futureInterface
!=
nullptr
);
219
const
int
lastThread
= (
barrier
.
release
() == 0);
220
221
if
(
lastThread
&&
asynchronous
)
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.
228
bool
ThreadEngineBase
::
threadThrottleExit
()
229
{
230
return
barrier
.
releaseUnlessLast
();
231
}
232
233
void
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.
257
reportIfSuspensionDone
();
258
}
259
}
260
261
#
ifndef
QT_NO_EXCEPTIONS
262
}
catch
(
QException
&
e
) {
263
handleException
(
e
);
264
}
catch
(...) {
265
handleException
(
QUnhandledException
(
std
::
current_exception
()));
266
}
267
#
endif
268
threadExit
();
269
}
270
271
#
ifndef
QT_NO_EXCEPTIONS
272
273
void
ThreadEngineBase
::
handleException
(
const
QException
&
exception
)
274
{
275
if
(
futureInterface
) {
276
futureInterface
->
reportException
(
exception
);
277
}
else
{
278
QMutexLocker
lock
(&
mutex
);
279
if
(!
exceptionStore
.
hasException
())
280
exceptionStore
.
setException
(
exception
);
281
}
282
}
283
#
endif
284
285
286
}
// namespace QtConcurrent
287
288
QT_END_NAMESPACE
289
290
#
endif
// QT_NO_CONCURRENT
QtConcurrent::ThreadEngineBarrier
\inmodule QtConcurrent
Definition
qtconcurrentthreadengine.h:28
QtConcurrent::ThreadEngineBarrier::currentCount
int currentCount()
Definition
qtconcurrentthreadengine.cpp:108
QtConcurrent::ThreadEngineBarrier::wait
void wait()
Definition
qtconcurrentthreadengine.cpp:92
QtConcurrent::ThreadEngineBarrier::releaseUnlessLast
bool releaseUnlessLast()
Definition
qtconcurrentthreadengine.cpp:115
QtConcurrent::ThreadEngineBarrier::release
int release()
Definition
qtconcurrentthreadengine.cpp:71
QtConcurrent::ThreadEngineBarrier::ThreadEngineBarrier
ThreadEngineBarrier()
Definition
qtconcurrentthreadengine.cpp:53
QtConcurrent::ThreadEngineBarrier::acquire
void acquire()
Definition
qtconcurrentthreadengine.cpp:56
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QtConcurrent
\inmodule QtConcurrent
Definition
qtconcurrentiteratekernel.cpp:29
qtbase
src
concurrent
qtconcurrentthreadengine.cpp
Generated on
for Qt by
1.18.0