qthreadpool.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/thread/qthreadpool.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5-
6-
7-
8namespace { namespace Q_QGS_theInstance { typedef QThreadPool Type; QBasicAtomicInt guard = { QtGlobalStatic::Uninitialized }; __attribute__((visibility("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic::Initialized) guard.store(QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type ())) : value () { guard.store(QtGlobalStatic::Initialized); } } holder; return &holder.value; } } } static QGlobalStatic<QThreadPool, Q_QGS_theInstance::innerFunction, Q_QGS_theInstance::guard> theInstance;-
9-
10-
11-
12-
13class QThreadPoolThread : public QThread-
14{-
15public:-
16 QThreadPoolThread(QThreadPoolPrivate *manager);-
17 void run() override;-
18 void registerThreadInactive();-
19-
20 QWaitCondition runnableReady;-
21 QThreadPoolPrivate *manager;-
22 QRunnable *runnable;-
23};-
24QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager)-
25 :manager(manager), runnable(0)-
26{ }-
27-
28-
29-
30-
31void QThreadPoolThread::run()-
32{-
33 QMutexLocker locker(&manager->mutex);-
34 for(;;) {-
35 QRunnable *r = runnable;-
36 runnable = 0;-
37-
38 do {-
39 if (r) {-
40 const bool autoDelete = r->autoDelete();-
41-
42-
43-
44 locker.unlock();-
45-
46 try {-
47-
48 r->run();-
49-
50 } catch (...) {-
51 QMessageLogger(__FILE__, 96102, __PRETTY_FUNCTION__).warning("Qt Concurrent has caught an exception thrown from a worker thread.\n"-
52 "This is not supported, exceptions thrown in worker threads must be\n"-
53 "caught before control returns to Qt Concurrent.");-
54 registerThreadInactive();-
55 throw;-
56 }-
57-
58 locker.relock();-
59-
60 if (autoDelete && !--r->ref)-
61 delete r;-
62 }-
63-
64-
65 if (manager->tooManyThreadsActive())-
66 break;-
67-
68 r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0;-
69 } while (r != 0);-
70-
71 if (manager->isExiting) {-
72 registerThreadInactive();-
73 break;-
74 }-
75-
76-
77 bool expired = manager->tooManyThreadsActive();-
78 if (!expired) {-
79 manager->waitingThreads.enqueue(this);-
80 registerThreadInactive();-
81-
82 runnableReady.wait(locker.mutex(), manager->expiryTimeout);-
83 ++manager->activeThreads;-
84 if (manager->waitingThreads.removeOne(this))-
85 expired = true;-
86 }-
87 if (expired) {-
88 manager->expiredThreads.enqueue(this);-
89 registerThreadInactive();-
90 break;-
91 }-
92 }-
93}-
94-
95void QThreadPoolThread::registerThreadInactive()-
96{-
97 if (--manager->activeThreads == 0)-
98 manager->noActiveThreads.wakeAll();-
99}-
100-
101-
102-
103-
104-
105QThreadPoolPrivate:: QThreadPoolPrivate()-
106 : isExiting(false),-
107 expiryTimeout(30000),-
108 maxThreadCount(qAbs(QThread::idealThreadCount())),-
109 reservedThreads(0),-
110 activeThreads(0)-
111{ }-
112-
113bool QThreadPoolPrivate::tryStart(QRunnable *task)-
114{-
115 if (allThreads.isEmpty()) {-
116-
117 startThread(task);-
118 return true;-
119 }-
120-
121-
122 if (activeThreadCount() >= maxThreadCount)-
123 return false;-
124-
125 if (waitingThreads.count() > 0) {-
126-
127 enqueueTask(task);-
128 waitingThreads.takeFirst()->runnableReady.wakeOne();-
129 return true;-
130 }-
131-
132 if (!expiredThreads.isEmpty()) {-
133-
134 QThreadPoolThread *thread = expiredThreads.dequeue();-
135 ((!(thread->runnable == 0)) ? qt_assert("thread->runnable == 0",__FILE__,180186) : qt_noop());-
136-
137 ++activeThreads;-
138-
139 if (task->autoDelete())-
140 ++task->ref;-
141 thread->runnable = task;-
142 thread->start();-
143 return true;-
144 }-
145-
146-
147 startThread(task);-
148 return true;-
149}-
150-
151inline bool operator<(int priority, const QPair<QRunnable *, int> &p)-
152{ return p.second < priority; }-
153inline bool operator<(const QPair<QRunnable *, int> &p, int priority)-
154{ return priority < p.second; }-
155-
156void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)-
157{-
158 if (runnable->autoDelete())-
159 ++runnable->ref;-
160-
161-
162 QVector<QPair<QRunnable *, int> >::const_iterator begin = queue.constBegin();-
163 QVector<QPair<QRunnable *, int> >::const_iterator it = queue.constEnd();-
164 if (it != begin && priority > (*(it - 1)).second)-
165 it = std::upper_bound(begin, --it, priority);-
166 queue.insert(it - begin, qMakePair(runnable, priority));-
167}-
168-
169int QThreadPoolPrivate::activeThreadCount() const-
170{-
171 return (allThreads.count()-
172 - expiredThreads.count()-
173 - waitingThreads.count()-
174 + reservedThreads);-
175}-
176-
177void QThreadPoolPrivate::tryToStartMoreThreads()-
178{-
179-
180 while (!queue.isEmpty()
!queue.isEmpty()Description
TRUEevaluated 11 times by 1 test
Evaluated by:
  • tst_QThreadPool
FALSEevaluated 49801 times by 31 tests
Evaluated by:
  • tst_Lancelot
  • tst_NetworkSelfTest
  • tst_PlatformSocketEngine
  • tst_QAbstractNetworkCache
  • tst_QDebug
  • tst_QDnsLookup
  • tst_QDnsLookup_Appless
  • tst_QFtp
  • tst_QHostInfo
  • tst_QHttpNetworkConnection
  • tst_QHttpSocketEngine
  • tst_QIODevice
  • tst_QMimeDatabase
  • tst_QNetworkAccessManager_And_QProgressDialog
  • tst_QNetworkDiskCache
  • tst_QNetworkInterface
  • tst_QNetworkProxyFactory
  • tst_QObject
  • tst_QProcess
  • tst_QSocks5SocketEngine
  • tst_QSslSocket
  • tst_QSslSocket_onDemandCertificates_member
  • tst_QSslSocket_onDemandCertificates_static
  • tst_QTcpServer
  • tst_QTextCodec
  • ...
&& tryStart(queue.firstconstFirst().first)
tryStart(queue...First().first)Description
TRUEevaluated 9 times by 1 test
Evaluated by:
  • tst_QThreadPool
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QThreadPool
)
2-49801
181 queue.removeFirst();
executed 9 times by 1 test: queue.removeFirst();
Executed by:
  • tst_QThreadPool
9
182}
executed 49803 times by 31 tests: end of block
Executed by:
  • tst_Lancelot
  • tst_NetworkSelfTest
  • tst_PlatformSocketEngine
  • tst_QAbstractNetworkCache
  • tst_QDebug
  • tst_QDnsLookup
  • tst_QDnsLookup_Appless
  • tst_QFtp
  • tst_QHostInfo
  • tst_QHttpNetworkConnection
  • tst_QHttpSocketEngine
  • tst_QIODevice
  • tst_QMimeDatabase
  • tst_QNetworkAccessManager_And_QProgressDialog
  • tst_QNetworkDiskCache
  • tst_QNetworkInterface
  • tst_QNetworkProxyFactory
  • tst_QObject
  • tst_QProcess
  • tst_QSocks5SocketEngine
  • tst_QSslSocket
  • tst_QSslSocket_onDemandCertificates_member
  • tst_QSslSocket_onDemandCertificates_static
  • tst_QTcpServer
  • tst_QTextCodec
  • ...
49803
183-
184bool QThreadPoolPrivate::tooManyThreadsActive() const-
185{-
186 const int activeThreadCount = this->activeThreadCount();-
187 return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1;-
188}-
189-
190-
191-
192-
193void QThreadPoolPrivate::startThread(QRunnable *runnable)-
194{-
195 QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));-
196 thread->setObjectName(QLatin1String("Thread (pooled)"));-
197 allThreads.insert(thread.data());-
198 ++activeThreads;-
199-
200 if (runnable->autoDelete())-
201 ++runnable->ref;-
202 thread->runnable = runnable;-
203 thread.take()->start();-
204}-
205-
206-
207-
208-
209-
210void QThreadPoolPrivate::reset()-
211{-
212 QMutexLocker locker(&mutex);-
213 isExiting = true;-
214-
215 while (!allThreads.empty()
!allThreads.empty()Description
TRUEevaluated 957 times by 37 tests
Evaluated by:
  • tst_QDnsLookup_Appless
  • tst_QFuture
  • tst_QHostInfo
  • tst_QPointer
  • tst_QSslSocket
  • tst_QSslSocket_onDemandCertificates_member
  • tst_QSslSocket_onDemandCertificates_static
  • tst_QTcpSocket
  • tst_QTextCodec
  • tst_QThreadPool
  • tst_QtConcurrentRun
  • tst_lancelot - unknown status
  • tst_qdebug - unknown status
  • tst_qdnslookup - unknown status
  • tst_qftp - unknown status
  • tst_qfuturewatcher - unknown status
  • tst_qhostinfo - unknown status
  • tst_qhttpnetworkconnection - unknown status
  • tst_qhttpsocketengine - unknown status
  • tst_qlockfile - unknown status
  • tst_qmimedatabase-cache - unknown status
  • tst_qmimedatabase-xml - unknown status
  • tst_qnetworkdiskcache - unknown status
  • tst_qnetworkproxyfactory - unknown status
  • tst_qobject - unknown status
  • ...
FALSEevaluated 4780 times by 440 tests
Evaluated by:
  • tst_QApplication
  • tst_QCommandLineParser
  • tst_QCoreApplication
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDnsLookup_Appless
  • tst_QFuture
  • tst_QGlobal
  • tst_QGuiApplication
  • tst_QHostInfo
  • tst_QNetworkConfigurationManager
  • tst_QPointer
  • tst_QSql
  • tst_QSslSocket
  • tst_QSslSocket_onDemandCertificates_member
  • tst_QSslSocket_onDemandCertificates_static
  • tst_QTcpSocket
  • tst_QTextCodec
  • tst_QThreadPool
  • tst_QtConcurrentRun
  • tst_compiler - unknown status
  • tst_gestures - unknown status
  • tst_lancelot - unknown status
  • tst_languagechange - unknown status
  • ...
) {
957-4780
216-
217 QSet<QThreadPoolThread *> allThreadsCopy;-
218 allThreadsCopy.swap(allThreads);-
219 locker.unlock();-
220-
221 for (QForeachContainer<typename QtPrivate::remove_reference<decltype(allThreadsCopy)>::type> _container_((allThreadsCopy)); _container_.control && _container_.i != _container_.e; ++_container_.i, _container_.control ^= 1)for (QThreadPoolThread *thread = *_container_.i; _container_.control; _container_.control = 0): qAsConst(allThreadsCopy)) {-
222 thread->runnableReady.wakeAll();-
223 thread->wait();-
224 delete thread;-
225 }
executed 1182 times by 37 tests: end of block
Executed by:
  • tst_QDnsLookup_Appless
  • tst_QFuture
  • tst_QHostInfo
  • tst_QPointer
  • tst_QSslSocket
  • tst_QSslSocket_onDemandCertificates_member
  • tst_QSslSocket_onDemandCertificates_static
  • tst_QTcpSocket
  • tst_QTextCodec
  • tst_QThreadPool
  • tst_QtConcurrentRun
  • tst_lancelot - unknown status
  • tst_qdebug - unknown status
  • tst_qdnslookup - unknown status
  • tst_qftp - unknown status
  • tst_qfuturewatcher - unknown status
  • tst_qhostinfo - unknown status
  • tst_qhttpnetworkconnection - unknown status
  • tst_qhttpsocketengine - unknown status
  • tst_qlockfile - unknown status
  • tst_qmimedatabase-cache - unknown status
  • tst_qmimedatabase-xml - unknown status
  • tst_qnetworkdiskcache - unknown status
  • tst_qnetworkproxyfactory - unknown status
  • tst_qobject - unknown status
  • ...
1182
226-
227 locker.relock();-
228-
229 }
executed 957 times by 37 tests: end of block
Executed by:
  • tst_QDnsLookup_Appless
  • tst_QFuture
  • tst_QHostInfo
  • tst_QPointer
  • tst_QSslSocket
  • tst_QSslSocket_onDemandCertificates_member
  • tst_QSslSocket_onDemandCertificates_static
  • tst_QTcpSocket
  • tst_QTextCodec
  • tst_QThreadPool
  • tst_QtConcurrentRun
  • tst_lancelot - unknown status
  • tst_qdebug - unknown status
  • tst_qdnslookup - unknown status
  • tst_qftp - unknown status
  • tst_qfuturewatcher - unknown status
  • tst_qhostinfo - unknown status
  • tst_qhttpnetworkconnection - unknown status
  • tst_qhttpsocketengine - unknown status
  • tst_qlockfile - unknown status
  • tst_qmimedatabase-cache - unknown status
  • tst_qmimedatabase-xml - unknown status
  • tst_qnetworkdiskcache - unknown status
  • tst_qnetworkproxyfactory - unknown status
  • tst_qobject - unknown status
  • ...
957
230-
231 waitingThreads.clear();-
232 expiredThreads.clear();-
233-
234 isExiting = false;-
235}
executed 4780 times by 440 tests: end of block
Executed by:
  • tst_QApplication
  • tst_QCommandLineParser
  • tst_QCoreApplication
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDnsLookup_Appless
  • tst_QFuture
  • tst_QGlobal
  • tst_QGuiApplication
  • tst_QHostInfo
  • tst_QNetworkConfigurationManager
  • tst_QPointer
  • tst_QSql
  • tst_QSslSocket
  • tst_QSslSocket_onDemandCertificates_member
  • tst_QSslSocket_onDemandCertificates_static
  • tst_QTcpSocket
  • tst_QTextCodec
  • tst_QThreadPool
  • tst_QtConcurrentRun
  • tst_compiler - unknown status
  • tst_gestures - unknown status
  • tst_lancelot - unknown status
  • tst_languagechange - unknown status
  • ...
4780
236-
237bool QThreadPoolPrivate::waitForDone(int msecs)-
238{-
239 QMutexLocker locker(&mutex);-
240 if (msecs < 0) {-
241 while (!(queue.isEmpty() && activeThreads == 0))-
242 noActiveThreads.wait(locker.mutex());-
243 } else {-
244 QElapsedTimer timer;-
245 timer.start();-
246 int t;-
247 while (!(queue.isEmpty() && activeThreads == 0) &&-
248 ((t = msecs - timer.elapsed()) > 0))-
249 noActiveThreads.wait(locker.mutex(), t);-
250 }-
251 return queue.isEmpty() && activeThreads == 0;-
252}-
253-
254void QThreadPoolPrivate::clear()-
255{-
256 QMutexLocker locker(&mutex);-
257 for (QVector<QPair<QRunnable *, int> >::const_iterator it = queue.constBegin();-
258 it != queue.constEnd(); ++it) {-
259 QRunnable* r = it->first;-
260 if (r->autoDelete() && !--r->ref)-
261 delete r;-
262 }-
263 queue.clear();-
264}-
265-
266-
267-
268-
269-
270-
271bool QThreadPoolPrivate::stealRunnable(QRunnable *runnable)-
272{-
273 if (runnable == 0)-
274 return false;-
275 {-
276 QMutexLocker locker(&mutex);-
277 QVector<QPair<QRunnable *, int> >::iterator it = queue.begin();-
278 QVector<QPair<QRunnable *, int> >::iterator end = queue.end();-
279-
280 while (it != end) {-
281 if (it->first == runnable) {-
282 queue.erase(it);-
283 return true;-
284 }-
285 ++it;-
286 }-
287 }-
288-
289 return false;-
290}-
291-
292-
293-
294-
295-
296-
297-
298void QThreadPoolPrivate::stealAndRunRunnable(QRunnable *runnable)-
299{-
300 if (!stealRunnable(runnable))-
301 return;-
302 const bool autoDelete = runnable->autoDelete();-
303 bool del = autoDelete && !--runnable->ref;-
304-
305 runnable->run();-
306-
307 if (del) {-
308 delete runnable;-
309 }-
310}-
311QThreadPool::QThreadPool(QObject *parent)-
312 : QObject(*new QThreadPoolPrivate, parent)-
313{ }-
314-
315-
316-
317-
318-
319QThreadPool::~QThreadPool()-
320{-
321 waitForDone();-
322}-
323-
324-
325-
326-
327QThreadPool *QThreadPool::globalInstance()-
328{-
329 return theInstance();-
330}-
331void QThreadPool::start(QRunnable *runnable, int priority)-
332{-
333 if (!runnable)-
334 return;-
335-
336 QThreadPoolPrivate * const d = d_func();-
337 QMutexLocker locker(&d->mutex);-
338 if (!d->tryStart(runnable)) {-
339 d->enqueueTask(runnable, priority);-
340-
341 if (!d->waitingThreads.isEmpty())-
342 d->waitingThreads.takeFirst()->runnableReady.wakeOne();-
343 }-
344}-
345bool QThreadPool::tryStart(QRunnable *runnable)-
346{-
347 if (!runnable)-
348 return false;-
349-
350 QThreadPoolPrivate * const d = d_func();-
351-
352 QMutexLocker locker(&d->mutex);-
353-
354 if (d->allThreads.isEmpty() == false && d->activeThreadCount() >= d->maxThreadCount)-
355 return false;-
356-
357 return d->tryStart(runnable);-
358}-
359int QThreadPool::expiryTimeout() const-
360{-
361 const QThreadPoolPrivate * const d = d_func();-
362 return d->expiryTimeout;-
363}-
364-
365void QThreadPool::setExpiryTimeout(int expiryTimeout)-
366{-
367 QThreadPoolPrivate * const d = d_func();-
368 if (d->expiryTimeout == expiryTimeout)-
369 return;-
370 d->expiryTimeout = expiryTimeout;-
371}-
372int QThreadPool::maxThreadCount() const-
373{-
374 const QThreadPoolPrivate * const d = d_func();-
375 return d->maxThreadCount;-
376}-
377-
378void QThreadPool::setMaxThreadCount(int maxThreadCount)-
379{-
380 QThreadPoolPrivate * const d = d_func();-
381 QMutexLocker locker(&d->mutex);-
382-
383 if (maxThreadCount == d->maxThreadCount)-
384 return;-
385-
386 d->maxThreadCount = maxThreadCount;-
387 d->tryToStartMoreThreads();-
388}-
389int QThreadPool::activeThreadCount() const-
390{-
391 const QThreadPoolPrivate * const d = d_func();-
392 QMutexLocker locker(&d->mutex);-
393 return d->activeThreadCount();-
394}-
395void QThreadPool::reserveThread()-
396{-
397 QThreadPoolPrivate * const d = d_func();-
398 QMutexLocker locker(&d->mutex);-
399 ++d->reservedThreads;-
400}-
401void QThreadPool::releaseThread()-
402{-
403 QThreadPoolPrivate * const d = d_func();-
404 QMutexLocker locker(&d->mutex);-
405 --d->reservedThreads;-
406 d->tryToStartMoreThreads();-
407}-
408-
409-
410-
411-
412-
413-
414-
415bool QThreadPool::waitForDone(int msecs)-
416{-
417 QThreadPoolPrivate * const d = d_func();-
418 bool rc = d->waitForDone(msecs);-
419 if (rc)-
420 d->reset();-
421 return rc;-
422}-
423void QThreadPool::clear()-
424{-
425 QThreadPoolPrivate * const d = d_func();-
426 d->clear();-
427}-
428void QThreadPool::cancel(QRunnable *runnable)-
429{-
430 QThreadPoolPrivate * const d = d_func();-
431 if (!d->stealRunnable(runnable))-
432 return;-
433 if (runnable->autoDelete() && !--runnable->ref) {-
434 delete runnable;-
435 }-
436}-
437-
438-
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9