djkah11
djkah11

Reputation: 456

QThread threadpool

I am trying to write thread poll with QThread.

class ThreadPool: public QObject
{
    Q_OBJECT

public:
    ThreadPool(int maxThreads);
    void addTask(MyTask *task);
private:
    int maxThreads;
    QMutex mutex;
    QVector<QPair<bool, QThread>> threads;
    QThread *getFreeThread();
public slots:
   void freeThread();
};


void ThreadPool::addTask(MyTask* task)
{
    QThread *thread = getFreeThread();
    task->moveToThread(thread);
    connect(thread, SIGNAL(started()), task, SLOT(doWork()));
    connect(task, SIGNAL(workFinished()), thread, SLOT(quit()));
    connect(thread, SIGNAL(finished()), task, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), this, SLOT(freeThread()));
    thread->start();
}

I am creating a limited number of threads in which I want to perform tasks. However, I do not understand how to get the number of the freed thread. I know about QThreadPool and Qtconcurrent, but I dont want to use it. Perhaps, it is worth noting at each thread in QPair's vector is it free or not.

Upvotes: 0

Views: 1579

Answers (1)

psibar
psibar

Reputation: 2000

  1. you do not really need a QVector<QPair<bool, QThread>> to keep track of all the threads in your Pool, instead use a QList< QThread* > which holds only the pointers to the free threads.

    private:
         QList<QThread*> freeThreads; // only free threads
         QList<QThread*> allThreads; // just to count the number of all threads
    
  2. In the slot freeThread() use the sender() method from QObject to get the pointer of the signal sender, which in this case will be the QThread, that has become free

    void ThreadPool::freeThread()
    {
         // get the pointer to the thread that sent the signal:
         QObject* threadFreed = QObject::sender();
         if( ! freeThreads.contains( threadFreed ) )
         {
              // save the thread pointer in list
              freeThreads << threadFreed;
         }
    }
    
  3. Finally getFreeThread() can look like this:

    QThread* getFreeThread()
    {
         if( ! freeThreads.isEmpty() )
         {
              // take the first free thread
              return freeThreads.takeFirst();
         }
         else
         {
              if(allThreads.size() < maxThreads )
              {
                 // create a new thread 
                 QThread* thread = new QThread(this);
                 allThreads << thread;
                 return thread;
              }
              else
              {
                // Maximum number of threads exceeded 
                // and no free thread is available
                 return NULL;
              }
         }
    
    }
    

Also you should handle the case when a NULL pointer is returned in addTask:

void ThreadPool::addTask(MyTask* task)
{
    QThread *thread = getFreeThread();
    if( ! thread )
    {
        // do something else
        return;
    }
    // proceed with thread execution ...
}

Upvotes: 2

Related Questions