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
qthreadpool.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
"qthreadpool.h"
6
#
include
"qthreadpool_p.h"
7
#
include
"qdeadlinetimer.h"
8
#
include
"qcoreapplication.h"
9
10
#
include
<
QtCore
/
qpointer
.
h
>
11
12
#
include
<
algorithm
>
13
#
include
<
climits
>
// For INT_MAX
14
#
include
<
memory
>
15
16
using
namespace
std
::chrono_literals;
17
18
QT_BEGIN_NAMESPACE
19
20
using
namespace
Qt::StringLiterals;
21
22
namespace
{
23
struct
QThreadGlobalPool
24
{
25
QPointer<QThreadPool> theInstance;
26
};
27
QBasicMutex theMutex;
28
}
29
Q_GLOBAL_STATIC(QThreadGlobalPool, globalPool)
30
31
/*
32
QThread wrapper, provides synchronization against a ThreadPool
33
*/
34
class
QThreadPoolThread
:
public
QThread
35
{
36
Q_OBJECT
37
public
:
38
QThreadPoolThread
(
QThreadPoolPrivate
*
manager
);
39
void
run
()
override
;
40
void
registerThreadInactive
();
41
42
QWaitCondition
runnableReady
;
43
QThreadPoolPrivate
*
manager
;
44
QRunnable
*
runnable
;
45
};
46
47
/*
48
QThreadPool private class.
49
*/
50
using
QueuePage
=
QThreadPoolPrivate
::
QueuePage
;
51
52
/*!
53
\internal
54
*/
55
QThreadPoolThread
::QThreadPoolThread(
QThreadPoolPrivate
*manager)
56
:
manager
(manager), runnable(
nullptr
)
57
{
58
setStackSize(manager->stackSize);
59
}
60
61
/*
62
\internal
63
*/
64
void
QThreadPoolThread
::
run
()
65
{
66
QMutexLocker locker(&
manager
->mutex);
67
for
(;;) {
68
QRunnable *r = runnable;
69
runnable =
nullptr
;
70
71
do
{
72
if
(r) {
73
// If autoDelete() is false, r might already be deleted after run(), so check status now.
74
const
bool
del = r->autoDelete();
75
76
// run the task
77
locker.unlock();
78
#
ifndef
QT_NO_EXCEPTIONS
79
try
{
80
#
endif
81
r->run();
82
#
ifndef
QT_NO_EXCEPTIONS
83
}
catch
(...) {
84
qWarning(
"Qt Concurrent has caught an exception thrown from a worker thread.\n"
85
"This is not supported, exceptions thrown in worker threads must be\n"
86
"caught before control returns to Qt Concurrent."
);
87
registerThreadInactive
(
)
;
88
throw
;
89
}
90
#
endif
91
92
if
(del)
93
delete
r;
94
locker.relock();
95
}
96
97
// if too many threads are active, stop working in this one
98
if
(
manager
->
tooManyThreadsActive
(
)
)
99
break
;
100
101
// all work is done, time to wait for more
102
if
(
manager
->queue.isEmpty())
103
break
;
104
105
QueuePage
*page =
manager
->queue.constFirst();
106
r = page->pop();
107
108
if
(page
->
isFinished
(
)
) {
109
manager
->queue.removeFirst();
110
delete
page;
111
}
112
}
while
(
true
);
113
114
// this thread is about to be deleted, do not wait or expire
115
if
(!
manager
->allThreads.contains(
this
)) {
116
registerThreadInactive
(
)
;
117
return
;
118
}
119
120
// if too many threads are active, expire this thread
121
if
(
manager
->
tooManyThreadsActive
(
)
) {
122
manager
->expiredThreads.enqueue(
this
);
123
registerThreadInactive
(
)
;
124
return
;
125
}
126
manager
->waitingThreads.enqueue(
this
);
127
registerThreadInactive
(
)
;
128
// wait for work, exiting after the expiry timeout is reached
129
runnableReady.wait(locker.mutex(), QDeadlineTimer(manager->expiryTimeout));
130
// this thread is about to be deleted, do not work or expire
131
if
(!
manager
->allThreads.contains(
this
)) {
132
Q_ASSERT(
manager
->queue.isEmpty());
133
return
;
134
}
135
if
(
manager
->waitingThreads.removeOne(
this
)) {
136
manager
->expiredThreads.enqueue(
this
);
137
return
;
138
}
139
++
manager
->
activeThreads
;
140
}
141
}
142
143
void
QThreadPoolThread
::
registerThreadInactive
()
144
{
145
if
(--
manager
->
activeThreads
== 0)
146
manager
->noActiveThreads.wakeAll();
147
}
148
149
150
/*
151
\internal
152
*/
153
QThreadPoolPrivate
::
QThreadPoolPrivate
()
154
{ }
155
156
void
QThreadPoolPrivate
::
destroyGlobalThreadPool
()
157
{
158
if
(!globalPool.exists())
159
return
;
160
161
QThreadPool *globalThreadPool = []{
162
const
QMutexLocker locker(&theMutex);
163
QThreadPool *p = globalPool->theInstance.get();
164
globalPool->theInstance =
nullptr
;
165
return
p;
166
}();
167
if
(globalThreadPool)
168
delete
globalThreadPool;
169
}
170
171
bool
QThreadPoolPrivate
::
tryStart
(QRunnable *task)
172
{
173
Q_ASSERT(task !=
nullptr
);
174
if
(allThreads.isEmpty()) {
175
// always create at least one thread
176
startThread(task);
177
return
true
;
178
}
179
180
// can't do anything if we're over the limit
181
if
(
areAllThreadsActive
(
)
)
182
return
false
;
183
184
if
(!waitingThreads.isEmpty()) {
185
// recycle an available thread
186
enqueueTask(task);
187
waitingThreads.takeFirst()->runnableReady.wakeOne();
188
return
true
;
189
}
190
191
if
(!expiredThreads.isEmpty()) {
192
// restart an expired thread
193
QThreadPoolThread
*thread = expiredThreads.dequeue();
194
Q_ASSERT(thread->runnable ==
nullptr
);
195
196
++
activeThreads
;
197
198
thread->runnable = task;
199
200
// Ensure that the thread has actually finished, otherwise the following
201
// start() has no effect.
202
thread->wait();
203
Q_ASSERT(thread->isFinished());
204
thread->start(threadPriority);
205
return
true
;
206
}
207
208
// start a new thread
209
startThread(task);
210
return
true
;
211
}
212
213
inline
bool
comparePriority
(
int
priority,
const
QueuePage
*p)
214
{
215
return
p
->
priority
(
)
< priority;
216
}
217
218
void
QThreadPoolPrivate
::
enqueueTask
(QRunnable *runnable,
int
priority)
219
{
220
Q_ASSERT(runnable !=
nullptr
);
221
for
(QueuePage *page : std::as_const(queue)) {
222
if
(page->priority() == priority && !page->isFull()) {
223
page->push(runnable);
224
return
;
225
}
226
}
227
auto
it =
std
::upper_bound(queue.constBegin(), queue.constEnd(), priority,
comparePriority
);
228
queue.insert(std::distance(queue.constBegin(), it),
new
QueuePage(runnable, priority));
229
}
230
231
int
QThreadPoolPrivate
::
activeThreadCount
()
const
232
{
233
return
(allThreads.size()
234
- expiredThreads.size()
235
- waitingThreads.size()
236
+ reservedThreads);
237
}
238
239
void
QThreadPoolPrivate
::
tryToStartMoreThreads
()
240
{
241
// try to push tasks on the queue to any available threads
242
while
(!queue.isEmpty()) {
243
QueuePage
*page = queue.constFirst();
244
if
(!tryStart(page->first()))
245
break
;
246
247
page->pop();
248
249
if
(page
->
isFinished
(
)
) {
250
queue.removeFirst();
251
delete
page;
252
}
253
}
254
}
255
256
bool
QThreadPoolPrivate
::
areAllThreadsActive
()
const
257
{
258
const
int
activeThreadCount =
this
->
activeThreadCount
(
)
;
259
return
activeThreadCount >=
maxThreadCount
(
)
&& (activeThreadCount -
reservedThreads
) >= 1;
260
}
261
262
bool
QThreadPoolPrivate
::
tooManyThreadsActive
()
const
263
{
264
const
int
activeThreadCount =
this
->
activeThreadCount
(
)
;
265
return
activeThreadCount >
maxThreadCount
(
)
&& (activeThreadCount -
reservedThreads
) > 1;
266
}
267
268
/*!
269
\internal
270
*/
271
void
QThreadPoolPrivate
::
startThread
(QRunnable *runnable)
272
{
273
Q_ASSERT(runnable !=
nullptr
);
274
auto
thread =
std
::make_unique<
QThreadPoolThread
>(
this
);
275
if
(objectName.isEmpty())
276
objectName = u"Thread (pooled)"_s;
277
thread->setObjectName(objectName);
278
thread->setServiceLevel(serviceLevel);
279
Q_ASSERT(!allThreads.contains(thread.get()));
// if this assert hits, we have an ABA problem (deleted threads don't get removed here)
280
allThreads.insert(thread.get());
281
++
activeThreads
;
282
283
thread->runnable = runnable;
284
thread.release()->start(threadPriority);
285
}
286
287
/*!
288
\internal
289
290
Helper function only to be called from waitForDone()
291
292
Deletes all current threads.
293
*/
294
void
QThreadPoolPrivate
::
reset
()
295
{
296
// move the contents of the set out so that we can iterate without the lock
297
auto
allThreadsCopy = std::exchange(allThreads, {});
298
expiredThreads.clear();
299
waitingThreads.clear();
300
301
mutex.unlock();
302
303
for
(QThreadPoolThread *thread : std::as_const(allThreadsCopy)) {
304
if
(thread->isRunning()) {
305
thread->runnableReady.wakeAll();
306
thread->wait();
307
}
308
delete
thread;
309
}
310
311
mutex.lock();
312
}
313
314
/*!
315
\internal
316
317
Helper function only to be called from the public waitForDone()
318
*/
319
bool
QThreadPoolPrivate
::
waitForDone
(
const
QDeadlineTimer &timer)
320
{
321
QMutexLocker locker(&mutex);
322
while
(!(queue.isEmpty() && activeThreads == 0) && !timer.hasExpired())
323
noActiveThreads.wait(&mutex, timer);
324
325
if
(!queue.isEmpty() || activeThreads)
326
return
false
;
327
328
reset
(
)
;
329
// New jobs might have started during reset, but return anyway
330
// as the active thread and task count did reach 0 once, and
331
// race conditions are outside our scope.
332
return
true
;
333
}
334
335
void
QThreadPoolPrivate
::
clear
()
336
{
337
QMutexLocker locker(&mutex);
338
while
(!queue.isEmpty()) {
339
auto
*page = queue.takeLast();
340
while
(!page->isFinished()) {
341
QRunnable *r = page->pop();
342
if
(r && r->autoDelete()) {
343
locker.unlock();
344
delete
r;
345
locker.relock();
346
}
347
}
348
delete
page;
349
}
350
}
351
352
/*!
353
\since 5.9
354
355
Attempts to remove the specified \a runnable from the queue if it is not yet started.
356
If the runnable had not been started, returns \c true, and ownership of \a runnable
357
is transferred to the caller (even when \c{runnable->autoDelete() == true}).
358
Otherwise returns \c false.
359
360
\note If \c{runnable->autoDelete() == true}, this function may remove the wrong
361
runnable. This is known as the \l{https://en.wikipedia.org/wiki/ABA_problem}{ABA problem}:
362
the original \a runnable may already have executed and has since been deleted.
363
The memory is re-used for another runnable, which then gets removed instead of
364
the intended one. For this reason, we recommend calling this function only for
365
runnables that are not auto-deleting.
366
367
\sa start(), QRunnable::autoDelete()
368
*/
369
bool
QThreadPool::tryTake(QRunnable *runnable)
370
{
371
Q_D(QThreadPool);
372
373
if
(runnable ==
nullptr
)
374
return
false
;
375
376
QMutexLocker locker(&d->mutex);
377
for
(QueuePage *page : std::as_const(d->queue)) {
378
if
(page->tryTake(runnable)) {
379
if
(page->isFinished()) {
380
d->queue.removeOne(page);
381
delete
page;
382
}
383
return
true
;
384
}
385
}
386
387
return
false
;
388
}
389
390
/*!
391
\internal
392
Searches for \a runnable in the queue, removes it from the queue and
393
runs it if found. This function does not return until the runnable
394
has completed.
395
*/
396
void
QThreadPoolPrivate
::
stealAndRunRunnable
(QRunnable *runnable)
397
{
398
Q_Q(QThreadPool);
399
if
(!q->tryTake(runnable))
400
return
;
401
// If autoDelete() is false, runnable might already be deleted after run(), so check status now.
402
const
bool
del = runnable->autoDelete();
403
404
runnable->run();
405
406
if
(del)
407
delete
runnable;
408
}
409
410
/*!
411
\class QThreadPool
412
\inmodule QtCore
413
\brief The QThreadPool class manages a collection of QThreads.
414
\since 4.4
415
\threadsafe
416
417
\ingroup thread
418
419
QThreadPool manages and recycles individual QThread objects to help reduce
420
thread creation costs in programs that use threads. Each Qt application
421
has one global QThreadPool object, which can be accessed by calling
422
globalInstance().
423
424
To use one of the QThreadPool threads, subclass QRunnable and implement
425
the run() virtual function. Then create an object of that class and pass
426
it to QThreadPool::start().
427
428
\snippet code/src_corelib_concurrent_qthreadpool.cpp 0
429
430
QThreadPool deletes the QRunnable automatically by default. Use
431
QRunnable::setAutoDelete() to change the auto-deletion flag.
432
433
QThreadPool supports executing the same QRunnable more than once
434
by calling tryStart(this) from within QRunnable::run().
435
If autoDelete is enabled the QRunnable will be deleted when
436
the last thread exits the run function. Calling start()
437
multiple times with the same QRunnable when autoDelete is enabled
438
creates a race condition and is not recommended.
439
440
Threads that are unused for a certain amount of time will expire. The
441
default expiry timeout is 30000 milliseconds (30 seconds). This can be
442
changed using setExpiryTimeout(). Setting a negative expiry timeout
443
disables the expiry mechanism.
444
445
Call maxThreadCount() to query the maximum number of threads to be used.
446
If needed, you can change the limit with setMaxThreadCount(). The default
447
maxThreadCount() is QThread::idealThreadCount(). The activeThreadCount()
448
function returns the number of threads currently doing work.
449
450
The reserveThread() function reserves a thread for external
451
use. Use releaseThread() when your are done with the thread, so
452
that it may be reused. Essentially, these functions temporarily
453
increase or reduce the active thread count and are useful when
454
implementing time-consuming operations that are not visible to the
455
QThreadPool.
456
457
Note that QThreadPool is a low-level class for managing threads, see
458
the Qt Concurrent module for higher level alternatives.
459
460
\sa QRunnable
461
*/
462
463
/*!
464
Constructs a thread pool with the given \a parent.
465
*/
466
QThreadPool::QThreadPool(QObject *parent)
467
: QObject(*
new
QThreadPoolPrivate, parent)
468
{
469
Q_D(QThreadPool);
470
connect(
this
, &QObject::objectNameChanged,
this
, [d](
const
QString &newName) {
471
// We keep a copy of the name under our own lock, so we can access it thread-safely.
472
QMutexLocker locker(&d->mutex);
473
d->objectName = newName;
474
});
475
}
476
477
/*!
478
Destroys the QThreadPool.
479
This function will block until all runnables have been completed.
480
*/
481
QThreadPool::~QThreadPool()
482
{
483
Q_D(QThreadPool);
484
waitForDone();
485
Q_ASSERT(d->queue.isEmpty());
486
Q_ASSERT(d->allThreads.isEmpty());
487
}
488
489
/*!
490
Returns the global QThreadPool instance.
491
*/
492
QThreadPool *QThreadPool::globalInstance()
493
{
494
if
(!globalPool.exists() && QCoreApplication::closingDown())
495
return
nullptr
;
// don't create
496
497
QPointer<QThreadPool> &theInstance = globalPool->theInstance;
498
const
QMutexLocker locker(&theMutex);
499
if
(!theInstance)
500
theInstance =
new
QThreadPool();
501
return
theInstance;
502
}
503
504
/*!
505
Reserves a thread and uses it to run \a runnable, unless this thread will
506
make the current thread count exceed maxThreadCount(). In that case,
507
\a runnable is added to a run queue instead. The \a priority argument can
508
be used to control the run queue's order of execution.
509
510
Note that the thread pool takes ownership of the \a runnable if
511
\l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c true,
512
and the \a runnable will be deleted automatically by the thread
513
pool after the \l{QRunnable::run()}{runnable->run()} returns. If
514
\l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c false,
515
ownership of \a runnable remains with the caller. Note that
516
changing the auto-deletion on \a runnable after calling this
517
functions results in undefined behavior.
518
*/
519
void
QThreadPool::start(QRunnable *runnable,
int
priority)
520
{
521
if
(!runnable)
522
return
;
523
524
Q_D(QThreadPool);
525
QMutexLocker locker(&d->mutex);
526
527
if
(!d->tryStart(runnable))
528
d->enqueueTask(runnable, priority);
529
}
530
531
/*!
532
\fn template<typename Callable, QRunnable::if_callable<Callable>> void QThreadPool::start(Callable &&callableToRun, int priority)
533
\overload
534
\since 5.15
535
536
Reserves a thread and uses it to run \a callableToRun, unless this thread will
537
make the current thread count exceed maxThreadCount(). In that case,
538
\a callableToRun is added to a run queue instead. The \a priority argument can
539
be used to control the run queue's order of execution.
540
541
\note In Qt version prior to 6.6, this function took std::function<void()>,
542
and therefore couldn't handle move-only callables.
543
544
\constraints \c Callable
545
is a function or function object which can be called with zero arguments.
546
*/
547
548
/*!
549
Attempts to reserve a thread to run \a runnable.
550
551
If no threads are available at the time of calling, then this function
552
does nothing and returns \c false. Otherwise, \a runnable is run immediately
553
using one available thread and this function returns \c true.
554
555
Note that on success the thread pool takes ownership of the \a runnable if
556
\l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c true,
557
and the \a runnable will be deleted automatically by the thread
558
pool after the \l{QRunnable::run()}{runnable->run()} returns. If
559
\l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c false,
560
ownership of \a runnable remains with the caller. Note that
561
changing the auto-deletion on \a runnable after calling this
562
function results in undefined behavior.
563
*/
564
bool
QThreadPool::tryStart(QRunnable *runnable)
565
{
566
if
(!runnable)
567
return
false
;
568
569
Q_D(QThreadPool);
570
QMutexLocker locker(&d->mutex);
571
if
(d->tryStart(runnable))
572
return
true
;
573
574
return
false
;
575
}
576
577
/*!
578
\fn template<typename Callable, QRunnable::if_callable<Callable>> bool QThreadPool::tryStart(Callable &&callableToRun)
579
\overload
580
\since 5.15
581
Attempts to reserve a thread to run \a callableToRun.
582
583
If no threads are available at the time of calling, then this function
584
does nothing and returns \c false. Otherwise, \a callableToRun is run immediately
585
using one available thread and this function returns \c true.
586
587
\note In Qt version prior to 6.6, this function took std::function<void()>,
588
and therefore couldn't handle move-only callables.
589
590
\constraints \c Callable
591
is a function or function object which can be called with zero arguments.
592
*/
593
594
/*! \property QThreadPool::expiryTimeout
595
\brief the thread expiry timeout value in milliseconds.
596
597
Threads that are unused for \e expiryTimeout milliseconds are considered
598
to have expired and will exit. Such threads will be restarted as needed.
599
The default \a expiryTimeout is 30000 milliseconds (30 seconds). If
600
\a expiryTimeout is negative, newly created threads will not expire, e.g.,
601
they will not exit until the thread pool is destroyed.
602
603
Note that setting \a expiryTimeout has no effect on already running
604
threads. Only newly created threads will use the new \a expiryTimeout.
605
We recommend setting the \a expiryTimeout immediately after creating the
606
thread pool, but before calling start().
607
*/
608
609
int
QThreadPool::expiryTimeout()
const
610
{
611
using
namespace
std::chrono;
612
Q_D(
const
QThreadPool);
613
QMutexLocker locker(&d->mutex);
614
if
(d->expiryTimeout ==
decltype
(d->expiryTimeout)::max())
615
return
-1;
616
return
duration_cast<milliseconds>(d->expiryTimeout).count();
617
}
618
619
void
QThreadPool::setExpiryTimeout(
int
expiryTimeout)
620
{
621
Q_D(QThreadPool);
622
QMutexLocker locker(&d->mutex);
623
if
(expiryTimeout < 0)
624
d->expiryTimeout =
decltype
(d->expiryTimeout)::max();
625
else
626
d->expiryTimeout = expiryTimeout * 1ms;
627
}
628
629
/*! \property QThreadPool::maxThreadCount
630
631
\brief the maximum number of threads used by the thread pool. This property
632
will default to the value of QThread::idealThreadCount() at the moment the
633
QThreadPool object is created.
634
635
\note The thread pool will always use at least 1 thread, even if
636
\a maxThreadCount limit is zero or negative.
637
638
The default \a maxThreadCount is QThread::idealThreadCount().
639
*/
640
641
int
QThreadPool::maxThreadCount()
const
642
{
643
Q_D(
const
QThreadPool);
644
QMutexLocker locker(&d->mutex);
645
return
d->requestedMaxThreadCount;
646
}
647
648
void
QThreadPool::setMaxThreadCount(
int
maxThreadCount)
649
{
650
Q_D(QThreadPool);
651
QMutexLocker locker(&d->mutex);
652
653
if
(maxThreadCount == d->requestedMaxThreadCount)
654
return
;
655
656
d->requestedMaxThreadCount = maxThreadCount;
657
d->tryToStartMoreThreads();
658
}
659
660
/*! \property QThreadPool::activeThreadCount
661
662
\brief the number of active threads in the thread pool.
663
664
\note It is possible for this function to return a value that is greater
665
than maxThreadCount(). See reserveThread() for more details.
666
667
\sa reserveThread(), releaseThread()
668
*/
669
670
int
QThreadPool::activeThreadCount()
const
671
{
672
Q_D(
const
QThreadPool);
673
QMutexLocker locker(&d->mutex);
674
return
d->activeThreadCount();
675
}
676
677
/*!
678
Reserves one thread, disregarding activeThreadCount() and maxThreadCount().
679
680
Once you are done with the thread, call releaseThread() to allow it to be
681
reused.
682
683
\note Even if reserving maxThreadCount() threads or more, the thread pool
684
will still allow a minimum of one thread.
685
686
\note This function will increase the reported number of active threads.
687
This means that by using this function, it is possible for
688
activeThreadCount() to return a value greater than maxThreadCount() .
689
690
\sa releaseThread()
691
*/
692
void
QThreadPool::reserveThread()
693
{
694
Q_D(QThreadPool);
695
QMutexLocker locker(&d->mutex);
696
++d->reservedThreads;
697
}
698
699
/*! \property QThreadPool::stackSize
700
\brief the stack size for the thread pool worker threads.
701
702
The value of the property is only used when the thread pool creates
703
new threads. Changing it has no effect for already created
704
or running threads.
705
706
The default value is 0, which makes QThread use the operating
707
system default stack size.
708
709
\since 5.10
710
*/
711
void
QThreadPool::setStackSize(uint stackSize)
712
{
713
Q_D(QThreadPool);
714
QMutexLocker locker(&d->mutex);
715
d->stackSize = stackSize;
716
}
717
718
uint QThreadPool::stackSize()
const
719
{
720
Q_D(
const
QThreadPool);
721
QMutexLocker locker(&d->mutex);
722
return
d->stackSize;
723
}
724
725
/*! \property QThreadPool::threadPriority
726
\brief the thread priority for new worker threads.
727
728
The value of the property is only used when the thread pool starts
729
new threads. Changing it has no effect for already running threads.
730
731
The default value is QThread::InheritPriority, which makes QThread
732
use the same priority as the one the QThreadPool object lives in.
733
734
\sa QThread::Priority
735
736
\since 6.2
737
*/
738
739
void
QThreadPool::setThreadPriority(QThread::Priority priority)
740
{
741
Q_D(QThreadPool);
742
QMutexLocker locker(&d->mutex);
743
d->threadPriority = priority;
744
}
745
746
QThread::Priority QThreadPool::threadPriority()
const
747
{
748
Q_D(
const
QThreadPool);
749
QMutexLocker locker(&d->mutex);
750
return
d->threadPriority;
751
}
752
753
/*!
754
Releases a thread previously reserved by a call to reserveThread().
755
756
\note Calling this function without previously reserving a thread
757
temporarily increases maxThreadCount(). This is useful when a
758
thread goes to sleep waiting for more work, allowing other threads
759
to continue. Be sure to call reserveThread() when done waiting, so
760
that the thread pool can correctly maintain the
761
activeThreadCount().
762
763
\sa reserveThread()
764
*/
765
void
QThreadPool::releaseThread()
766
{
767
Q_D(QThreadPool);
768
QMutexLocker locker(&d->mutex);
769
--d->reservedThreads;
770
d->tryToStartMoreThreads();
771
}
772
773
/*!
774
\since 6.9
775
776
Sets the Quality of Service level of thread objects created after the call
777
to this setter to \a serviceLevel.
778
779
Support is not available on every platform. Consult
780
QThread::setServiceLevel() for details.
781
782
\sa serviceLevel(), QThread::serviceLevel()
783
*/
784
void
QThreadPool::setServiceLevel(QThread::QualityOfService serviceLevel)
785
{
786
Q_D(QThreadPool);
787
QMutexLocker locker(&d->mutex);
788
d->serviceLevel = serviceLevel;
789
}
790
791
/*!
792
\since 6.9
793
794
Returns the current Quality of Service level of the thread.
795
796
\sa setServiceLevel(), QThread::serviceLevel()
797
*/
798
QThread::QualityOfService QThreadPool::serviceLevel()
const
799
{
800
Q_D(
const
QThreadPool);
801
QMutexLocker locker(&d->mutex);
802
return
d->serviceLevel;
803
}
804
805
/*!
806
Releases a thread previously reserved with reserveThread() and uses it
807
to run \a runnable.
808
809
Note that the thread pool takes ownership of the \a runnable if
810
\l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c true,
811
and the \a runnable will be deleted automatically by the thread
812
pool after the \l{QRunnable::run()}{runnable->run()} returns. If
813
\l{QRunnable::autoDelete()}{runnable->autoDelete()} returns \c false,
814
ownership of \a runnable remains with the caller. Note that
815
changing the auto-deletion on \a runnable after calling this
816
functions results in undefined behavior.
817
818
\note Calling this when no threads are reserved results in
819
undefined behavior.
820
821
\since 6.3
822
\sa reserveThread(), start()
823
*/
824
void
QThreadPool::startOnReservedThread(QRunnable *runnable)
825
{
826
if
(!runnable)
827
return
releaseThread();
828
829
Q_D(QThreadPool);
830
QMutexLocker locker(&d->mutex);
831
Q_ASSERT(d->reservedThreads > 0);
832
--d->reservedThreads;
833
834
if
(!d->tryStart(runnable)) {
835
// This can only happen if we reserved max threads,
836
// and something took the one minimum thread.
837
d->enqueueTask(runnable, INT_MAX);
838
}
839
}
840
841
/*!
842
\fn template<typename Callable, QRunnable::if_callable<Callable>> void QThreadPool::startOnReservedThread(Callable &&callableToRun)
843
\overload
844
\since 6.3
845
846
Releases a thread previously reserved with reserveThread() and uses it
847
to run \a callableToRun.
848
849
\note In Qt version prior to 6.6, this function took std::function<void()>,
850
and therefore couldn't handle move-only callables.
851
852
\constraints \c Callable
853
is a function or function object which can be called with zero arguments.
854
*/
855
856
/*!
857
\fn bool QThreadPool::waitForDone(int msecs)
858
Waits up to \a msecs milliseconds for all threads to exit and removes all
859
threads from the thread pool. Returns \c true if all threads were removed;
860
otherwise it returns \c false. If \a msecs is -1, this function waits for
861
the last thread to exit.
862
*/
863
864
/*!
865
\since 6.8
866
867
Waits until \a deadline expires for all threads to exit and removes all
868
threads from the thread pool. Returns \c true if all threads were removed;
869
otherwise it returns \c false.
870
*/
871
bool
QThreadPool::waitForDone(QDeadlineTimer deadline)
872
{
873
Q_D(QThreadPool);
874
return
d->waitForDone(deadline);
875
}
876
877
/*!
878
\since 5.2
879
880
Removes the runnables that are not yet started from the queue.
881
The runnables for which \l{QRunnable::autoDelete()}{runnable->autoDelete()}
882
returns \c true are deleted.
883
884
\sa start()
885
*/
886
void
QThreadPool::clear()
887
{
888
Q_D(QThreadPool);
889
d->clear();
890
}
891
892
/*!
893
\since 6.0
894
895
Returns \c true if \a thread is a thread managed by this thread pool.
896
*/
897
bool
QThreadPool::contains(
const
QThread *thread)
const
898
{
899
Q_D(
const
QThreadPool);
900
const
QThreadPoolThread *poolThread = qobject_cast<
const
QThreadPoolThread *>(thread);
901
if
(!poolThread)
902
return
false
;
903
QMutexLocker locker(&d->mutex);
904
return
d->allThreads.contains(
const_cast
<QThreadPoolThread *>(poolThread));
905
}
906
907
QT_END_NAMESPACE
908
909
#
include
"moc_qthreadpool.cpp"
910
#
include
"qthreadpool.moc"
QThreadPoolPrivate
Definition
qthreadpool_p.h:34
QThreadPoolPrivate::areAllThreadsActive
bool areAllThreadsActive() const
Definition
qthreadpool.cpp:256
QThreadPoolPrivate::tryStart
bool tryStart(QRunnable *task)
Definition
qthreadpool.cpp:171
QThreadPoolPrivate::enqueueTask
void enqueueTask(QRunnable *task, int priority=0)
Definition
qthreadpool.cpp:218
QThreadPoolPrivate::reset
void reset()
Definition
qthreadpool.cpp:294
QThreadPoolPrivate::QThreadPoolPrivate
QThreadPoolPrivate()
Definition
qthreadpool.cpp:153
QThreadPoolPrivate::tryToStartMoreThreads
void tryToStartMoreThreads()
Definition
qthreadpool.cpp:239
QThreadPoolPrivate::reservedThreads
int reservedThreads
Definition
qthreadpool_p.h:145
QThreadPoolPrivate::destroyGlobalThreadPool
static void destroyGlobalThreadPool()
Definition
qthreadpool.cpp:156
QThreadPoolPrivate::activeThreadCount
int activeThreadCount() const
Definition
qthreadpool.cpp:231
QThreadPoolPrivate::maxThreadCount
int maxThreadCount() const
Definition
qthreadpool_p.h:126
QThreadPoolPrivate::activeThreads
int activeThreads
Definition
qthreadpool_p.h:146
QThreadPoolPrivate::startThread
void startThread(QRunnable *runnable=nullptr)
Definition
qthreadpool.cpp:271
QThreadPoolPrivate::stealAndRunRunnable
void stealAndRunRunnable(QRunnable *runnable)
Definition
qthreadpool.cpp:396
QThreadPoolPrivate::clear
void clear()
Definition
qthreadpool.cpp:335
QThreadPoolPrivate::waitForDone
bool waitForDone(const QDeadlineTimer &timer)
Definition
qthreadpool.cpp:319
QThreadPoolPrivate::tooManyThreadsActive
bool tooManyThreadsActive() const
Definition
qthreadpool.cpp:262
QThreadPoolThread
Definition
qthreadpool.cpp:35
QThreadPoolThread::run
void run() override
Definition
qthreadpool.cpp:64
QThreadPoolThread::manager
QThreadPoolPrivate * manager
Definition
qthreadpool.cpp:43
QThreadPoolThread::registerThreadInactive
void registerThreadInactive()
Definition
qthreadpool.cpp:143
QThreadPoolThread::runnable
QRunnable * runnable
Definition
qthreadpool.cpp:44
QThreadPoolThread::runnableReady
QWaitCondition runnableReady
Definition
qthreadpool.cpp:42
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
comparePriority
bool comparePriority(int priority, const QueuePage *p)
Definition
qthreadpool.cpp:213
QueuePage
QThreadPoolPrivate::QueuePage QueuePage
Definition
qthreadpool.cpp:50
QThreadPoolPrivate::QueuePage
Definition
qthreadpool_p.h:40
QThreadPoolPrivate::QueuePage::priority
int priority() const
Definition
qthreadpool_p.h:106
QThreadPoolPrivate::QueuePage::isFinished
bool isFinished()
Definition
qthreadpool_p.h:49
qtbase
src
corelib
thread
qthreadpool.cpp
Generated on
for Qt by
1.18.0