In Qt 4.7 Reference for QThreadPool
, we find:
void QThreadPool::releaseThread()
Releases a thread previously reserved by a call to
reserveThread()
.Note: Calling this function without previously reserving a thread temporarily increases
maxThreadCount()
. This is useful when a thread goes to sleep waiting for more work, allowing other threads to continue. Be sure to callreserveThread()
when done waiting, so that the thread pool can correctly maintain theactiveThreadCount()
.See also
reserveThread()
.
void QThreadPool::reserveThread()
Reserves one thread, disregarding
activeThreadCount()
andmaxThreadCount()
.Once you are done with the thread, call
releaseThread()
to allow it to be reused.Note: This function will always increase the number of active threads. This means that by using this function, it is possible for
activeThreadCount()
to return a value greater thanmaxThreadCount()
.See also
releaseThread()
.
I want to use releaseThread()
to make it possible to use nested concurrent map, but in the following code, it hangs in waitForFinished()
:
#include <QApplication>
#include <QMainWindow>
#include <QtConcurrentMap>
#include <QtConcurrentRun>
#include <QFuture>
#include <QThreadPool>
#include <QtTest/QTest>
#include <QFutureSynchronizer>
struct Task2 { // only calculation
typedef void result_type;
void operator()(int count) {
int k = 0;
for (int i = 0; i < count * 10; ++i) {
for (int j = 0; j < count * 10; ++j) {
k++;
}
}
assert(k >= 0);
}
};
struct Task1 { // will launch some other concurrent map
typedef void result_type;
void operator()(int count) {
QVector<int> vec;
for (int i = 0; i < 5; ++i) {
vec.push_back(i+count);
}
Task2 task;
QFuture<void> f = QtConcurrent::map(vec.begin(), vec.end(), task);
{
// with out releaseThread before wait, it will hang directly
QThreadPool::globalInstance()->releaseThread();
f.waitForFinished(); // BUG: may hang there
QThreadPool::globalInstance()->reserveThread();
}
}
};
int main() {
QThreadPool* gtpool = QThreadPool::globalInstance();
gtpool->setExpiryTimeout(50);
int count = 0;
for (;;) {
QVector<int> vec;
for (int i = 0; i < 40 ; i++) {
vec.push_back(i);
}
// launch a task with nested map
Task1 task; // Task1 will have nested concurrent map
QFuture<void> f = QtConcurrent::map(vec.begin(), vec.end(),task);
f.waitForFinished(); // BUG: may hang there
count++;
// waiting most of thread in thread pool expire
while (QThreadPool::globalInstance()->activeThreadCount() > 0) {
QTest::qSleep(50);
}
// launch a task only calculation
Task2 task2;
QFuture<void> f2 = QtConcurrent::map(vec.begin(), vec.end(), task2);
f2.waitForFinished(); // BUG: may hang there
qDebug() << count;
}
return 0;
}
This code will not run forever; it will hang in after many loops (1~10000), with all threads waiting for condition variable.
My questions are:
- Why does it hang?
- Can I fix it and keep the nested concurrent map?
dev env:
Linux version 2.6.32-696.18.7.el6.x86_64; Qt4.7.4; GCC 3.4.5
Windows 7; Qt4.7.4; mingw 4.4.0