QThreadPool Class
Today, we decide to use the thread pool to build our application. So I need to know the mechanism of qt thread pool class.
To see the document, I get to know the qt thread pool is used by QThreadPool and QRunnable classes.
To create a thread by using qt thread pool is so easy. Let’s look at the implementation code.
class HelloWorldTask : public QRunnable
{
void run()
{
qDebug() << "Hello world from thread" << QThread::currentThread();
}
}
HelloWorldTask *hello = new HelloWorldTask();
// QThreadPool takes ownership and deletes 'hello' automatically
QThreadPool::globalInstance()->start(hello);
All the functions in this class are thread-safe.
First of all, let’s come to the QThreadPool class. The path is corelib/concurrent/qthreadpool.h
The QThreadPool inherits from the QObject, so it is the member of meta-object system. And in this class, we can use the characteristics of signals and slots.
At the beginning, I’m interested in the globalInstance () function.
QThreadPool *QThreadPool::globalInstance()
{
return theInstance();
}
The only row is the cell the theInstance () function.
To create this function by the following codes,
Q_GLOBAL_STATIC(QThreadPool, theInstance)
We have see this macro before.
And then, let’s look at the start () function.
void QThreadPool::start(QRunnable *runnable, int priority)
{
if (!runnable)
return;
Q_D(QThreadPool);
QMutexLocker locker(&d->mutex);
if (!d->tryStart(runnable))
d->enqueueTask(runnable, priority);
}
I getting to know the Q_D macro is to get the data point of QThreadPool. The data point’s name is d.
And this Q_D is supported by define the Q_DECLARE_PRIVATE() macro. Here is this macro’s codes,
#define Q_DECLARE_PRIVATE(Class) /
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } /
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } /
friend class Class##Private;
The true realization of the code is in the enqueueTask () function from QThreadPoolPrivate class.
void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
{
if (runnable->autoDelete())
++runnable->ref;
// put it on the queue
QList<QPair<QRunnable *, int> >::iterator at =
qUpperBound(queue.begin(), queue.end(), priority);
queue.insert(at, qMakePair(runnable, priority));
runnableReady.wakeOne();
}
This function put the point of QRunnable on the queue to manage. And I guess this sentence is wake an waiting thread.
runnableReady.wakeOne();
After do it, we don’t know how to continue. So we should to know the structure of QThreadPoolPrivate.
But it is time to go to sleep. This will be the tomorrow’s task.
November 12, 2009 23:34