thread/qthreadpool.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtCore module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qthreadpool.h" -
43#include "qthreadpool_p.h" -
44#include "qelapsedtimer.h" -
45 -
46#include <algorithm> -
47 -
48#ifndef QT_NO_THREAD -
49 -
50QT_BEGIN_NAMESPACE -
51 -
52Q_GLOBAL_STATIC(QThreadPool, theInstance)
never executed: delete x;
executed: return thisGlobalStatic.pointer.load();
Execution Count:3266734
partially evaluated: !thisGlobalStatic.pointer.testAndSetOrdered(0, x)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:343
evaluated: !thisGlobalStatic.pointer.load()
TRUEFALSE
yes
Evaluation Count:343
yes
Evaluation Count:3266542
partially evaluated: !thisGlobalStatic.destroyed
TRUEFALSE
yes
Evaluation Count:343
no
Evaluation Count:0
0-3266734
53 -
54/* -
55 QThread wrapper, provides synchronizitaion against a ThreadPool -
56*/ -
57class QThreadPoolThread : public QThread -
58{ -
59public: -
60 QThreadPoolThread(QThreadPoolPrivate *manager); -
61 void run(); -
62 void registerTheadInactive(); -
63 -
64 QThreadPoolPrivate *manager; -
65 QRunnable *runnable; -
66}; -
67 -
68/* -
69 QThreadPool private class. -
70*/ -
71 -
72 -
73/*! -
74 \internal -
75*/ -
76QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager) -
77 :manager(manager), runnable(0) -
78{ }
executed: }
Execution Count:2373
2373
79 -
80/* -
81 \internal -
82*/ -
83void QThreadPoolThread::run() -
84{ -
85 QMutexLocker locker(&manager->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&manager->mutex);
-
86 for(;;) {
executed (the execution status of this line is deduced): for(;;) {
-
87 QRunnable *r = runnable;
executed (the execution status of this line is deduced): QRunnable *r = runnable;
-
88 runnable = 0;
executed (the execution status of this line is deduced): runnable = 0;
-
89 -
90 do { -
91 if (r) {
evaluated: r
TRUEFALSE
yes
Evaluation Count:5294639
yes
Evaluation Count:5274917
5274917-5294639
92 const bool autoDelete = r->autoDelete();
executed (the execution status of this line is deduced): const bool autoDelete = r->autoDelete();
-
93 -
94 -
95 // run the task -
96 locker.unlock();
executed (the execution status of this line is deduced): locker.unlock();
-
97#ifndef QT_NO_EXCEPTIONS -
98 try { -
99#endif -
100 r->run();
executed (the execution status of this line is deduced): r->run();
-
101#ifndef QT_NO_EXCEPTIONS -
102 } catch (...) {
executed: }
Execution Count:5293120
5293120
103 qWarning("Qt Concurrent has caught an exception thrown from a worker thread.\n"
never executed (the execution status of this line is deduced): QMessageLogger("thread/qthreadpool.cpp", 103, __PRETTY_FUNCTION__).warning("Qt Concurrent has caught an exception thrown from a worker thread.\n"
-
104 "This is not supported, exceptions thrown in worker threads must be\n"
never executed (the execution status of this line is deduced): "This is not supported, exceptions thrown in worker threads must be\n"
-
105 "caught before control returns to Qt Concurrent.");
never executed (the execution status of this line is deduced): "caught before control returns to Qt Concurrent.");
-
106 registerTheadInactive();
never executed (the execution status of this line is deduced): registerTheadInactive();
-
107 throw;
never executed: throw;
0
108 } -
109#endif -
110 locker.relock();
executed (the execution status of this line is deduced): locker.relock();
-
111 -
112 if (autoDelete && !--r->ref)
evaluated: autoDelete
TRUEFALSE
yes
Evaluation Count:2868387
yes
Evaluation Count:2426252
partially evaluated: !--r->ref
TRUEFALSE
yes
Evaluation Count:2868387
no
Evaluation Count:0
0-2868387
113 delete r;
executed: delete r;
Execution Count:2868387
2868387
114 }
executed: }
Execution Count:5294639
5294639
115 -
116 // if too many threads are active, expire this thread -
117 if (manager->tooManyThreadsActive())
evaluated: manager->tooManyThreadsActive()
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:10569554
2-10569554
118 break;
executed: break;
Execution Count:2
2
119 -
120 r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0;
evaluated: !manager->queue.isEmpty()
TRUEFALSE
yes
Evaluation Count:5292259
yes
Evaluation Count:5277295
5277295-5292259
121 } while (r != 0);
executed: }
Execution Count:10569554
evaluated: r != 0
TRUEFALSE
yes
Evaluation Count:5292259
yes
Evaluation Count:5277295
5277295-10569554
122 -
123 if (manager->isExiting) {
evaluated: manager->isExiting
TRUEFALSE
yes
Evaluation Count:2380
yes
Evaluation Count:5274917
2380-5274917
124 registerTheadInactive();
executed (the execution status of this line is deduced): registerTheadInactive();
-
125 break;
executed: break;
Execution Count:2380
2380
126 } -
127 -
128 // if too many threads are active, expire this thread -
129 bool expired = manager->tooManyThreadsActive();
executed (the execution status of this line is deduced): bool expired = manager->tooManyThreadsActive();
-
130 if (!expired) {
evaluated: !expired
TRUEFALSE
yes
Evaluation Count:5274915
yes
Evaluation Count:2
2-5274915
131 ++manager->waitingThreads;
executed (the execution status of this line is deduced): ++manager->waitingThreads;
-
132 registerTheadInactive();
executed (the execution status of this line is deduced): registerTheadInactive();
-
133 // wait for work, exiting after the expiry timeout is reached -
134 expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout);
executed (the execution status of this line is deduced): expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout);
-
135 ++manager->activeThreads;
executed (the execution status of this line is deduced): ++manager->activeThreads;
-
136 -
137 if (expired)
evaluated: expired
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:5274917
6-5274917
138 --manager->waitingThreads;
executed: --manager->waitingThreads;
Execution Count:6
6
139 }
executed: }
Execution Count:5274923
5274923
140 if (expired) {
evaluated: expired
TRUEFALSE
yes
Evaluation Count:8
yes
Evaluation Count:5274917
8-5274917
141 manager->expiredThreads.enqueue(this);
executed (the execution status of this line is deduced): manager->expiredThreads.enqueue(this);
-
142 registerTheadInactive();
executed (the execution status of this line is deduced): registerTheadInactive();
-
143 break;
executed: break;
Execution Count:8
8
144 } -
145 }
executed: }
Execution Count:5274917
5274917
146}
executed: }
Execution Count:2388
2388
147 -
148void QThreadPoolThread::registerTheadInactive() -
149{ -
150 if (--manager->activeThreads == 0)
evaluated: --manager->activeThreads == 0
TRUEFALSE
yes
Evaluation Count:3647374
yes
Evaluation Count:1629929
1629929-3647374
151 manager->noActiveThreads.wakeAll();
executed: manager->noActiveThreads.wakeAll();
Execution Count:3647374
3647374
152}
executed: }
Execution Count:5277303
5277303
153 -
154 -
155/* -
156 \internal -
157*/ -
158QThreadPoolPrivate:: QThreadPoolPrivate() -
159 : isExiting(false), -
160 expiryTimeout(30000), -
161 maxThreadCount(qAbs(QThread::idealThreadCount())), -
162 reservedThreads(0), -
163 waitingThreads(0), -
164 activeThreads(0) -
165{ }
executed: }
Execution Count:1008
1008
166 -
167bool QThreadPoolPrivate::tryStart(QRunnable *task) -
168{ -
169 if (allThreads.isEmpty()) {
evaluated: allThreads.isEmpty()
TRUEFALSE
yes
Evaluation Count:753
yes
Evaluation Count:5839291
753-5839291
170 // always create at least one thread -
171 startThread(task);
executed (the execution status of this line is deduced): startThread(task);
-
172 return true;
executed: return true;
Execution Count:753
753
173 } -
174 -
175 // can't do anything if we're over the limit -
176 if (activeThreadCount() >= maxThreadCount)
evaluated: activeThreadCount() >= maxThreadCount
TRUEFALSE
yes
Evaluation Count:565075
yes
Evaluation Count:5274216
565075-5274216
177 return false;
executed: return false;
Execution Count:565075
565075
178 -
179 if (waitingThreads > 0) {
evaluated: waitingThreads > 0
TRUEFALSE
yes
Evaluation Count:5272589
yes
Evaluation Count:1627
1627-5272589
180 // recycle an available thread -
181 --waitingThreads;
executed (the execution status of this line is deduced): --waitingThreads;
-
182 enqueueTask(task);
executed (the execution status of this line is deduced): enqueueTask(task);
-
183 return true;
executed: return true;
Execution Count:5272589
5272589
184 } -
185 -
186 if (!expiredThreads.isEmpty()) {
evaluated: !expiredThreads.isEmpty()
TRUEFALSE
yes
Evaluation Count:7
yes
Evaluation Count:1620
7-1620
187 // restart an expired thread -
188 QThreadPoolThread *thread = expiredThreads.dequeue();
executed (the execution status of this line is deduced): QThreadPoolThread *thread = expiredThreads.dequeue();
-
189 Q_ASSERT(thread->runnable == 0);
executed (the execution status of this line is deduced): qt_noop();
-
190 -
191 ++activeThreads;
executed (the execution status of this line is deduced): ++activeThreads;
-
192 -
193 if (task->autoDelete())
evaluated: task->autoDelete()
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:3
3-4
194 ++task->ref;
executed: ++task->ref;
Execution Count:4
4
195 thread->runnable = task;
executed (the execution status of this line is deduced): thread->runnable = task;
-
196 thread->start();
executed (the execution status of this line is deduced): thread->start();
-
197 return true;
executed: return true;
Execution Count:7
7
198 } -
199 -
200 // start a new thread -
201 startThread(task);
executed (the execution status of this line is deduced): startThread(task);
-
202 return true;
executed: return true;
Execution Count:1620
1620
203} -
204 -
205inline bool operator<(int priority, const QPair<QRunnable *, int> &p) -
206{ return p.second < priority; }
never executed: return p.second < priority;
0
207inline bool operator<(const QPair<QRunnable *, int> &p, int priority) -
208{ return priority < p.second; }
never executed: return priority < p.second;
0
209 -
210void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority) -
211{ -
212 if (runnable->autoDelete())
evaluated: runnable->autoDelete()
TRUEFALSE
yes
Evaluation Count:3390889
yes
Evaluation Count:2426185
2426185-3390889
213 ++runnable->ref;
executed: ++runnable->ref;
Execution Count:3390889
3390889
214 -
215 // put it on the queue -
216 QList<QPair<QRunnable *, int> >::const_iterator begin = queue.constBegin();
executed (the execution status of this line is deduced): QList<QPair<QRunnable *, int> >::const_iterator begin = queue.constBegin();
-
217 QList<QPair<QRunnable *, int> >::const_iterator it = queue.constEnd();
executed (the execution status of this line is deduced): QList<QPair<QRunnable *, int> >::const_iterator it = queue.constEnd();
-
218 if (it != begin && priority < (*(it - 1)).second)
evaluated: it != begin
TRUEFALSE
yes
Evaluation Count:1659207
yes
Evaluation Count:4157867
partially evaluated: priority < (*(it - 1)).second
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1659207
0-4157867
219 it = std::upper_bound(begin, --it, priority);
never executed: it = std::upper_bound(begin, --it, priority);
0
220 queue.insert(it - begin, qMakePair(runnable, priority));
executed (the execution status of this line is deduced): queue.insert(it - begin, qMakePair(runnable, priority));
-
221 runnableReady.wakeOne();
executed (the execution status of this line is deduced): runnableReady.wakeOne();
-
222}
executed: }
Execution Count:5817074
5817074
223 -
224int QThreadPoolPrivate::activeThreadCount() const -
225{ -
226 // To improve scalability this function is called without holding -
227 // the mutex lock -- keep it thread-safe. -
228 return (allThreads.count()
executed: return (allThreads.count() - expiredThreads.count() - waitingThreads + reservedThreads);
Execution Count:22177186
22177186
229 - expiredThreads.count()
executed: return (allThreads.count() - expiredThreads.count() - waitingThreads + reservedThreads);
Execution Count:22177186
22177186
230 - waitingThreads
executed: return (allThreads.count() - expiredThreads.count() - waitingThreads + reservedThreads);
Execution Count:22177186
22177186
231 + reservedThreads);
executed: return (allThreads.count() - expiredThreads.count() - waitingThreads + reservedThreads);
Execution Count:22177186
22177186
232} -
233 -
234void QThreadPoolPrivate::tryToStartMoreThreads() -
235{ -
236 // try to push tasks on the queue to any available threads -
237 while (!queue.isEmpty() && tryStart(queue.first().first))
evaluated: !queue.isEmpty()
TRUEFALSE
yes
Evaluation Count:11
yes
Evaluation Count:49811
evaluated: tryStart(queue.first().first)
TRUEFALSE
yes
Evaluation Count:9
yes
Evaluation Count:2
2-49811
238 queue.removeFirst();
executed: queue.removeFirst();
Execution Count:9
9
239}
executed: }
Execution Count:49813
49813
240 -
241bool QThreadPoolPrivate::tooManyThreadsActive() const -
242{ -
243 const int activeThreadCount = this->activeThreadCount();
executed (the execution status of this line is deduced): const int activeThreadCount = this->activeThreadCount();
-
244 return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1;
executed: return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1;
Execution Count:15844473
15844473
245} -
246 -
247/*! -
248 \internal -
249*/ -
250void QThreadPoolPrivate::startThread(QRunnable *runnable) -
251{ -
252 QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
executed (the execution status of this line is deduced): QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
-
253 thread->setObjectName(QLatin1String("Thread (pooled)"));
executed (the execution status of this line is deduced): thread->setObjectName(QLatin1String("Thread (pooled)"));
-
254 allThreads.insert(thread.data());
executed (the execution status of this line is deduced): allThreads.insert(thread.data());
-
255 ++activeThreads;
executed (the execution status of this line is deduced): ++activeThreads;
-
256 -
257 if (runnable->autoDelete())
evaluated: runnable->autoDelete()
TRUEFALSE
yes
Evaluation Count:2300
yes
Evaluation Count:73
73-2300
258 ++runnable->ref;
executed: ++runnable->ref;
Execution Count:2300
2300
259 thread->runnable = runnable;
executed (the execution status of this line is deduced): thread->runnable = runnable;
-
260 thread.take()->start();
executed (the execution status of this line is deduced): thread.take()->start();
-
261}
executed: }
Execution Count:2373
2373
262 -
263/*! -
264 \internal -
265 Makes all threads exit, waits for each tread to exit and deletes it. -
266*/ -
267void QThreadPoolPrivate::reset() -
268{ -
269 QMutexLocker locker(&mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&mutex);
-
270 isExiting = true;
executed (the execution status of this line is deduced): isExiting = true;
-
271 runnableReady.wakeAll();
executed (the execution status of this line is deduced): runnableReady.wakeAll();
-
272 -
273 while (!allThreads.empty()) {
evaluated: !allThreads.empty()
TRUEFALSE
yes
Evaluation Count:754
yes
Evaluation Count:1644
754-1644
274 // move the contents of the set out so that we can iterate without the lock -
275 QSet<QThreadPoolThread *> allThreadsCopy;
executed (the execution status of this line is deduced): QSet<QThreadPoolThread *> allThreadsCopy;
-
276 allThreadsCopy.swap(allThreads);
executed (the execution status of this line is deduced): allThreadsCopy.swap(allThreads);
-
277 locker.unlock();
executed (the execution status of this line is deduced): locker.unlock();
-
278 -
279 foreach (QThreadPoolThread *thread, allThreadsCopy) {
executed (the execution status of this line is deduced): for (QForeachContainer<__typeof__(allThreadsCopy)> _container_(allThreadsCopy); !_container_.brk && _container_.i != _container_.e; __extension__ ({ ++_container_.brk; ++_container_.i; })) for (QThreadPoolThread *thread = *_container_.i;; __extension__ ({--_container_.brk; break;})) {
-
280 thread->wait();
executed (the execution status of this line is deduced): thread->wait();
-
281 delete thread;
executed (the execution status of this line is deduced): delete thread;
-
282 }
executed: }
Execution Count:2381
2381
283 -
284 locker.relock();
executed (the execution status of this line is deduced): locker.relock();
-
285 // repeat until all newly arrived threads have also completed -
286 }
executed: }
Execution Count:754
754
287 -
288 waitingThreads = 0;
executed (the execution status of this line is deduced): waitingThreads = 0;
-
289 expiredThreads.clear();
executed (the execution status of this line is deduced): expiredThreads.clear();
-
290 -
291 isExiting = false;
executed (the execution status of this line is deduced): isExiting = false;
-
292}
executed: }
Execution Count:1644
1644
293 -
294bool QThreadPoolPrivate::waitForDone(int msecs) -
295{ -
296 QMutexLocker locker(&mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&mutex);
-
297 if (msecs < 0) {
evaluated: msecs < 0
TRUEFALSE
yes
Evaluation Count:1643
yes
Evaluation Count:2
2-1643
298 while (!(queue.isEmpty() && activeThreads == 0))
evaluated: queue.isEmpty()
TRUEFALSE
yes
Evaluation Count:2224
yes
Evaluation Count:29
evaluated: activeThreads == 0
TRUEFALSE
yes
Evaluation Count:1643
yes
Evaluation Count:581
29-2224
299 noActiveThreads.wait(locker.mutex());
executed: noActiveThreads.wait(locker.mutex());
Execution Count:610
610
300 } else {
executed: }
Execution Count:1643
1643
301 QElapsedTimer timer;
executed (the execution status of this line is deduced): QElapsedTimer timer;
-
302 timer.start();
executed (the execution status of this line is deduced): timer.start();
-
303 int t;
executed (the execution status of this line is deduced): int t;
-
304 while (!(queue.isEmpty() && activeThreads == 0) &&
partially evaluated: queue.isEmpty()
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
evaluated: activeThreads == 0
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:3
0-4
305 ((t = msecs - timer.elapsed()) > 0))
evaluated: ((t = msecs - timer.elapsed()) > 0)
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:1
1-2
306 noActiveThreads.wait(locker.mutex(), t);
executed: noActiveThreads.wait(locker.mutex(), t);
Execution Count:2
2
307 }
executed: }
Execution Count:2
2
308 return queue.isEmpty() && activeThreads == 0;
executed: return queue.isEmpty() && activeThreads == 0;
Execution Count:1645
1645
309} -
310 -
311/*! -
312 \internal -
313 Seaches for \a runnable in the queue, removes it from the queue and -
314 runs it if found. This functon does not return until the runnable -
315 has completed. -
316*/ -
317void QThreadPoolPrivate::stealRunnable(QRunnable *runnable) -
318{ -
319 if (runnable == 0)
evaluated: runnable == 0
TRUEFALSE
yes
Evaluation Count:43752
yes
Evaluation Count:520796
43752-520796
320 return;
executed: return;
Execution Count:43752
43752
321 bool found = false;
executed (the execution status of this line is deduced): bool found = false;
-
322 { -
323 QMutexLocker locker(&mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&mutex);
-
324 QList<QPair<QRunnable *, int> >::iterator it = queue.begin();
executed (the execution status of this line is deduced): QList<QPair<QRunnable *, int> >::iterator it = queue.begin();
-
325 QList<QPair<QRunnable *, int> >::iterator end = queue.end();
executed (the execution status of this line is deduced): QList<QPair<QRunnable *, int> >::iterator end = queue.end();
-
326 -
327 while (it != end) {
evaluated: it != end
TRUEFALSE
yes
Evaluation Count:11673679
yes
Evaluation Count:561
561-11673679
328 if (it->first == runnable) {
evaluated: it->first == runnable
TRUEFALSE
yes
Evaluation Count:524806
yes
Evaluation Count:11148873
524806-11148873
329 found = true;
executed (the execution status of this line is deduced): found = true;
-
330 queue.erase(it);
executed (the execution status of this line is deduced): queue.erase(it);
-
331 break;
executed: break;
Execution Count:524806
524806
332 } -
333 ++it;
executed (the execution status of this line is deduced): ++it;
-
334 }
executed: }
Execution Count:11148873
11148873
335 } -
336 -
337 if (!found)
evaluated: !found
TRUEFALSE
yes
Evaluation Count:561
yes
Evaluation Count:522772
561-522772
338 return;
executed: return;
Execution Count:561
561
339 -
340 const bool autoDelete = runnable->autoDelete();
executed (the execution status of this line is deduced): const bool autoDelete = runnable->autoDelete();
-
341 bool del = autoDelete && !--runnable->ref;
partially evaluated: autoDelete
TRUEFALSE
yes
Evaluation Count:522682
no
Evaluation Count:0
partially evaluated: !--runnable->ref
TRUEFALSE
yes
Evaluation Count:522487
no
Evaluation Count:0
0-522682
342 -
343 runnable->run();
executed (the execution status of this line is deduced): runnable->run();
-
344 -
345 if (del) {
partially evaluated: del
TRUEFALSE
yes
Evaluation Count:521116
no
Evaluation Count:0
0-521116
346 delete runnable;
executed (the execution status of this line is deduced): delete runnable;
-
347 }
executed: }
Execution Count:521208
521208
348}
executed: }
Execution Count:521194
521194
349 -
350/*! -
351 \class QThreadPool -
352 \inmodule QtCore -
353 \brief The QThreadPool class manages a collection of QThreads. -
354 \since 4.4 -
355 \threadsafe -
356 -
357 \ingroup thread -
358 -
359 QThreadPool manages and recyles individual QThread objects to help reduce -
360 thread creation costs in programs that use threads. Each Qt application -
361 has one global QThreadPool object, which can be accessed by calling -
362 globalInstance(). -
363 -
364 To use one of the QThreadPool threads, subclass QRunnable and implement -
365 the run() virtual function. Then create an object of that class and pass -
366 it to QThreadPool::start(). -
367 -
368 \snippet code/src_corelib_concurrent_qthreadpool.cpp 0 -
369 -
370 QThreadPool deletes the QRunnable automatically by default. Use -
371 QRunnable::setAutoDelete() to change the auto-deletion flag. -
372 -
373 QThreadPool supports executing the same QRunnable more than once -
374 by calling tryStart(this) from within QRunnable::run(). -
375 If autoDelete is enabled the QRunnable will be deleted when -
376 the last thread exits the run function. Calling start() -
377 multiple times with the same QRunnable when autoDelete is enabled -
378 creates a race condition and is not recommended. -
379 -
380 Threads that are unused for a certain amount of time will expire. The -
381 default expiry timeout is 30000 milliseconds (30 seconds). This can be -
382 changed using setExpiryTimeout(). Setting a negative expiry timeout -
383 disables the expiry mechanism. -
384 -
385 Call maxThreadCount() to query the maximum number of threads to be used. -
386 If needed, you can change the limit with setMaxThreadCount(). The default -
387 maxThreadCount() is QThread::idealThreadCount(). The activeThreadCount() -
388 function returns the number of threads currently doing work. -
389 -
390 The reserveThread() function reserves a thread for external -
391 use. Use releaseThread() when your are done with the thread, so -
392 that it may be reused. Essentially, these functions temporarily -
393 increase or reduce the active thread count and are useful when -
394 implementing time-consuming operations that are not visible to the -
395 QThreadPool. -
396 -
397 Note that QThreadPool is a low-level class for managing threads, see -
398 the Qt Concurrent module for higher level alternatives. -
399 -
400 \sa QRunnable -
401*/ -
402 -
403/*! -
404 Constructs a thread pool with the given \a parent. -
405*/ -
406QThreadPool::QThreadPool(QObject *parent) -
407 : QObject(*new QThreadPoolPrivate, parent) -
408{ }
executed: }
Execution Count:1008
1008
409 -
410/*! -
411 Destroys the QThreadPool. -
412 This function will block until all runnables have been completed. -
413*/ -
414QThreadPool::~QThreadPool() -
415{ -
416 waitForDone();
executed (the execution status of this line is deduced): waitForDone();
-
417}
executed: }
Execution Count:1010
1010
418 -
419/*! -
420 Returns the global QThreadPool instance. -
421*/ -
422QThreadPool *QThreadPool::globalInstance() -
423{ -
424 return theInstance();
executed: return theInstance();
Execution Count:3267503
3267503
425} -
426 -
427/*! -
428 Reserves a thread and uses it to run \a runnable, unless this thread will -
429 make the current thread count exceed maxThreadCount(). In that case, -
430 \a runnable is added to a run queue instead. The \a priority argument can -
431 be used to control the run queue's order of execution. -
432 -
433 Note that the thread pool takes ownership of the \a runnable if -
434 \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns true, -
435 and the \a runnable will be deleted automatically by the thread -
436 pool after the \l{QRunnable::run()}{runnable->run()} returns. If -
437 \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns false, -
438 ownership of \a runnable remains with the caller. Note that -
439 changing the auto-deletion on \a runnable after calling this -
440 functions results in undefined behavior. -
441*/ -
442void QThreadPool::start(QRunnable *runnable, int priority) -
443{ -
444 if (!runnable)
partially evaluated: !runnable
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:5526421
0-5526421
445 return;
never executed: return;
0
446 -
447 Q_D(QThreadPool);
executed (the execution status of this line is deduced): QThreadPoolPrivate * const d = d_func();
-
448 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
449 if (!d->tryStart(runnable))
evaluated: !d->tryStart(runnable)
TRUEFALSE
yes
Evaluation Count:544485
yes
Evaluation Count:4986686
544485-4986686
450 d->enqueueTask(runnable, priority);
executed: d->enqueueTask(runnable, priority);
Execution Count:544485
544485
451}
executed: }
Execution Count:5531171
5531171
452 -
453/*! -
454 Attempts to reserve a thread to run \a runnable. -
455 -
456 If no threads are available at the time of calling, then this function -
457 does nothing and returns false. Otherwise, \a runnable is run immediately -
458 using one available thread and this function returns true. -
459 -
460 Note that the thread pool takes ownership of the \a runnable if -
461 \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns true, -
462 and the \a runnable will be deleted automatically by the thread -
463 pool after the \l{QRunnable::run()}{runnable->run()} returns. If -
464 \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns false, -
465 ownership of \a runnable remains with the caller. Note that -
466 changing the auto-deletion on \a runnable after calling this -
467 function results in undefined behavior. -
468*/ -
469bool QThreadPool::tryStart(QRunnable *runnable) -
470{ -
471 if (!runnable)
partially evaluated: !runnable
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:450576
0-450576
472 return false;
never executed: return false;
0
473 -
474 Q_D(QThreadPool);
executed (the execution status of this line is deduced): QThreadPoolPrivate * const d = d_func();
-
475 -
476 // To improve scalability perform a check on the thread count -
477 // before locking the mutex. -
478 if (d->allThreads.isEmpty() == false && d->activeThreadCount() >= d->maxThreadCount)
evaluated: d->allThreads.isEmpty() == false
TRUEFALSE
yes
Evaluation Count:450384
yes
Evaluation Count:4
evaluated: d->activeThreadCount() >= d->maxThreadCount
TRUEFALSE
yes
Evaluation Count:141097
yes
Evaluation Count:308167
4-450384
479 return false;
executed: return false;
Execution Count:141400
141400
480 -
481 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
482 return d->tryStart(runnable);
executed: return d->tryStart(runnable);
Execution Count:308862
308862
483} -
484 -
485/*! \property QThreadPool::expiryTimeout -
486 -
487 Threads that are unused for \a expiryTimeout milliseconds are considered -
488 to have expired and will exit. Such threads will be restarted as needed. -
489 The default \a expiryTimeout is 30000 milliseconds (30 seconds). If -
490 \a expiryTimeout is negative, newly created threads will not expire, e.g., -
491 they will not exit until the thread pool is destroyed. -
492 -
493 Note that setting \a expiryTimeout has no effect on already running -
494 threads. Only newly created threads will use the new \a expiryTimeout. -
495 We recommend setting the \a expiryTimeout immediately after creating the -
496 thread pool, but before calling start(). -
497*/ -
498 -
499int QThreadPool::expiryTimeout() const -
500{ -
501 Q_D(const QThreadPool);
executed (the execution status of this line is deduced): const QThreadPoolPrivate * const d = d_func();
-
502 return d->expiryTimeout;
executed: return d->expiryTimeout;
Execution Count:3
3
503} -
504 -
505void QThreadPool::setExpiryTimeout(int expiryTimeout) -
506{ -
507 Q_D(QThreadPool);
executed (the execution status of this line is deduced): QThreadPoolPrivate * const d = d_func();
-
508 if (d->expiryTimeout == expiryTimeout)
partially evaluated: d->expiryTimeout == expiryTimeout
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2
0-2
509 return;
never executed: return;
0
510 d->expiryTimeout = expiryTimeout;
executed (the execution status of this line is deduced): d->expiryTimeout = expiryTimeout;
-
511}
executed: }
Execution Count:2
2
512 -
513/*! \property QThreadPool::maxThreadCount -
514 -
515 This property represents the maximum number of threads used by the thread -
516 pool. -
517 -
518 \note The thread pool will always use at least 1 thread, even if -
519 \a maxThreadCount limit is zero or negative. -
520 -
521 The default \a maxThreadCount is QThread::idealThreadCount(). -
522*/ -
523 -
524int QThreadPool::maxThreadCount() const -
525{ -
526 Q_D(const QThreadPool);
executed (the execution status of this line is deduced): const QThreadPoolPrivate * const d = d_func();
-
527 return d->maxThreadCount;
executed: return d->maxThreadCount;
Execution Count:26671
26671
528} -
529 -
530void QThreadPool::setMaxThreadCount(int maxThreadCount) -
531{ -
532 Q_D(QThreadPool);
executed (the execution status of this line is deduced): QThreadPoolPrivate * const d = d_func();
-
533 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
534 -
535 if (maxThreadCount == d->maxThreadCount)
partially evaluated: maxThreadCount == d->maxThreadCount
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:149
0-149
536 return;
never executed: return;
0
537 -
538 d->maxThreadCount = maxThreadCount;
executed (the execution status of this line is deduced): d->maxThreadCount = maxThreadCount;
-
539 d->tryToStartMoreThreads();
executed (the execution status of this line is deduced): d->tryToStartMoreThreads();
-
540}
executed: }
Execution Count:149
149
541 -
542/*! \property QThreadPool::activeThreadCount -
543 -
544 This property represents the number of active threads in the thread pool. -
545 -
546 \note It is possible for this function to return a value that is greater -
547 than maxThreadCount(). See reserveThread() for more details. -
548 -
549 \sa reserveThread(), releaseThread() -
550*/ -
551 -
552int QThreadPool::activeThreadCount() const -
553{ -
554 Q_D(const QThreadPool);
executed (the execution status of this line is deduced): const QThreadPoolPrivate * const d = d_func();
-
555 return d->activeThreadCount();
executed: return d->activeThreadCount();
Execution Count:49776
49776
556} -
557 -
558/*! -
559 Reserves one thread, disregarding activeThreadCount() and maxThreadCount(). -
560 -
561 Once you are done with the thread, call releaseThread() to allow it to be -
562 reused. -
563 -
564 \note This function will always increase the number of active threads. -
565 This means that by using this function, it is possible for -
566 activeThreadCount() to return a value greater than maxThreadCount() . -
567 -
568 \sa releaseThread() -
569 */ -
570void QThreadPool::reserveThread() -
571{ -
572 Q_D(QThreadPool);
executed (the execution status of this line is deduced): QThreadPoolPrivate * const d = d_func();
-
573 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
574 ++d->reservedThreads;
executed (the execution status of this line is deduced): ++d->reservedThreads;
-
575}
executed: }
Execution Count:49664
49664
576 -
577/*! -
578 Releases a thread previously reserved by a call to reserveThread(). -
579 -
580 \note Calling this function without previously reserving a thread -
581 temporarily increases maxThreadCount(). This is useful when a -
582 thread goes to sleep waiting for more work, allowing other threads -
583 to continue. Be sure to call reserveThread() when done waiting, so -
584 that the thread pool can correctly maintain the -
585 activeThreadCount(). -
586 -
587 \sa reserveThread() -
588*/ -
589void QThreadPool::releaseThread() -
590{ -
591 Q_D(QThreadPool);
executed (the execution status of this line is deduced): QThreadPoolPrivate * const d = d_func();
-
592 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
593 --d->reservedThreads;
executed (the execution status of this line is deduced): --d->reservedThreads;
-
594 d->tryToStartMoreThreads();
executed (the execution status of this line is deduced): d->tryToStartMoreThreads();
-
595}
executed: }
Execution Count:49664
49664
596 -
597/*! -
598 Waits up to \a msecs milliseconds for all threads to exit and removes all -
599 threads from the thread pool. Returns true if all threads were removed; -
600 otherwise it returns false. If \a msecs is -1 (the default), the timeout -
601 is ignored (waits for the last thread to exit). -
602*/ -
603bool QThreadPool::waitForDone(int msecs) -
604{ -
605 Q_D(QThreadPool);
executed (the execution status of this line is deduced): QThreadPoolPrivate * const d = d_func();
-
606 bool rc = d->waitForDone(msecs);
executed (the execution status of this line is deduced): bool rc = d->waitForDone(msecs);
-
607 if (rc)
evaluated: rc
TRUEFALSE
yes
Evaluation Count:1644
yes
Evaluation Count:1
1-1644
608 d->reset();
executed: d->reset();
Execution Count:1644
1644
609 return rc;
executed: return rc;
Execution Count:1645
1645
610} -
611 -
612QT_END_NAMESPACE -
613 -
614#endif -
615 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial