The Structure of QThreadPoolPrivate
Yesterday, we make an assay of QThreadPoolPrivate. But when we came to know the mechanism of enqueueTask () function, it has no way to know the underlying implementation. So we come to the QThreadPoolPrivate class today.
Now, let’s look at the QThreadPoolThread and the QThreadPoolPrivate class.
The QThreadPoolThread class is inherited from QThread.
/*
QThread wrapper, provides synchronizitaion against a ThreadPool
*/
class QThreadPoolThread : public QThread
{
public:
QThreadPoolThread(QThreadPoolPrivate *manager);
void run();
void registerTheadInactive();
QThreadPoolPrivate *manager;
QRunnable *runnable;
};
From the definition of this class, we can guess when the QThreadPool class was living, it create some object of QThreadPoolThread. Then hang the thread and wait for the QThreadPoolThread::start () function is called.
The thread object was hanged by the follow codes.
void QThreadPoolThread::run()
{
QMutexLocker locker(&manager->mutex);
for(;;) {
QRunnable *r = runnable;
runnable = 0;
do {
if (r) {
const bool autoDelete = r->autoDelete();
// run the task
locker.unlock();
#ifndef QT_NO_EXCEPTIONS
try {
#endif
r->run();
#ifndef QT_NO_EXCEPTIONS
} catch (...) {
qWarning("Qt Concurrent has caught an exception thrown from a worker thread./n"
"This is not supported, exceptions thrown in worker threads must be/n"
"caught before control returns to Qt Concurrent.");
registerTheadInactive();
throw;
}
#endif
locker.relock();
if (autoDelete && !--r->ref)
delete r;
}
// if too many threads are active, expire this thread
if (manager->tooManyThreadsActive())
break;
r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0;
} while (r != 0);
if (manager->isExiting) {
registerTheadInactive();
break;
}
// if too many threads are active, expire this thread
bool expired = manager->tooManyThreadsActive();
if (!expired) {
++manager->waitingThreads;
registerTheadInactive();
// wait for work, exiting after the expiry timeout is reached
expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout);
++manager->activeThreads;
if (expired)
--manager->waitingThreads;
}
if (expired) {
manager->expiredThreads.enqueue(this);
registerTheadInactive();
break;
}
}
}
In order to support multi-thread synchronization, they create a QMutexLocker object by the following code.
QMutexLocker locker(&manager->mutex);
And then call an endless loop(for(;;)), after this, they create a point of QRunnable class.
QRunnable *r = runnable;
runnable = 0;
Here we can guess, this point points to the class, we create it by ourselves, which is inherited from QRunnable class. It is similar to the callback function.
Then they unlock the mutex, and run the task.
locker.unlock();
#ifndef QT_NO_EXCEPTIONS
try {
#endif
r->run();
#ifndef QT_NO_EXCEPTIONS
} catch (...) {
qWarning("Qt Concurrent has caught an exception thrown from a worker thread./n"
"This is not supported, exceptions thrown in worker threads must be/n"
"caught before control returns to Qt Concurrent.");
registerTheadInactive();
throw;
}
After the run () function returns. They do some cleaning work, and wait for the next task comes.
It’s time to go to sleep. That’s all for this class. The next day, I will do some analyze about the network framework.
November 13, 2009 23:41