Simple Thread Pool

As is mentioned in my pervious article Thread Management Class, I shall introduce a simple thread pool implemented by the CThread class. For more information about class IRunnable and CThread, please link to:

http://blog.csdn.net/sooner01/archive/2008/12/29/3639936.aspx

 

Firstly the class initializes some threads, and has the threads waiting to run some task. Then restore some task in to a queue, once the a task in submitted, a blocking thread is waken to run the task.

 

We can see the CSimpleThreadPool is derived from the IRunnable, and the virtual function run() is implement to be called by all thread function.

 

Here is the source code of the thread pool class.

//---------------------------- CLASS ----------------------------------------------------------

// A class containing a collection of CThreadTask's.

// Every CThreadTask will execute same CSimpleThreadPool::run() method.

class CSimpleThreadPool: public IRunnable {

private:

    QMutex                         m_qMutex;          // sync the access to m_PQueue

    vector<CThread*>               m_arrThreadTasks;  // restore the working thread

    mpriority_queue<CPriorityTask> m_PQueue;          // restore the task

    QSemaphore                     *m_pTaskQSemaphore; // notify the working thread

 

    // Method will return a task from the queue,

    // if there are no tasks in the queue, method will return NULL.

    IRunnable *get() {

        IRunnable *ret = NULL;

 

        m_qMutex.Lock();

        if (!m_PQueue.empty()) {

            CPriorityTask t = m_PQueue.top();

            m_PQueue.pop();

            ret = t.getTask();

        }

        m_qMutex.Unlock();

        return ret;

    };

 

public:

    // How many threads are in the collection.

    int threads() const {

        return m_arrThreadTasks.size();

    };

 

    // Method starts pool's threads.

    void startAll() {

        for (int i = 0; i < m_arrThreadTasks.size(); i++) {

            m_arrThreadTasks[i]->start();

        }

    };

 

    // Constructor creates the thread pool and sets capacity for the task queue.

    CSimpleThreadPool(unsigned int nThreadsCount, unsigned int nQueueCapacity = 16):

        m_qMutex(), m_PQueue(), m_pTaskQSemaphore(NULL) {

        int i;

        CThread *thTask = NULL;

 

        if (nThreadsCount <= 0) throw "Invalid number of threads supplied.";

        if (nQueueCapacity <= 0) throw "Invalid capacity supplied.";

 

        // Set initial capacity of the tasks Queue.

        // seems doesn't work

        m_PQueue.reserve(nQueueCapacity);

 

        // Initialize thread pool.

        for (i = 0; i < nThreadsCount; i++) {

            thTask = new CThread(this);

            if (thTask != NULL) m_arrThreadTasks.push_back(thTask);

        }

 

        // initialize the task semaphore

        m_pTaskQSemaphore = new QSemaphore(0, nQueueCapacity);

        if (NULL == m_pTaskQSemaphore) throw "Semaphore initialization error!";

    };

 

    // Submit a new task to the pool

    void submit(IRunnable *pRunObj, int nPriority = 0) {

        if (this == pRunObj) throw "Self referencing not allowed.";

 

        m_qMutex.Lock();

        m_PQueue.push(CPriorityTask(pRunObj, nPriority));

        m_qMutex.Unlock();

 

        // call a thread to work for new task

        m_pTaskQSemaphore->Dec();

    };

 

    // Method will execute task's run() method within its CThread context.

    virtual void run() {

        IRunnable *task;

 

        while (!CThread::currentThread().isInterrupted()) {

           

            // wait for a task

            m_pTaskQSemaphore->Inc();

 

            // Get a task from the queue.

            task = get();

 

            // Execute the task.

            if (task != NULL) task->run();

        }

    };

 

    virtual ~CSimpleThreadPool() {

        vector<CThread*>::iterator itPos = m_arrThreadTasks.begin();

 

        for (; itPos < m_arrThreadTasks.end(); itPos++) delete *itPos;

        m_arrThreadTasks.clear();

 

        while (!m_PQueue.empty()) { m_PQueue.pop(); }

 

        if (m_pTaskQSemaphore != NULL) delete m_pTaskQSemaphore;

    };

 

    // Method signals threads to stop and waits for termination

    void shutdown() {

        for (int i = 0; i < m_arrThreadTasks.size(); i++) {

            m_arrThreadTasks[i]->interrupt();

        }

        // stop threads waiting

        m_pTaskQSemaphore->Dec(m_arrThreadTasks.size());

 

        // have all threads closed

        for (int i = 0; i < m_arrThreadTasks.size(); i++) {

            m_arrThreadTasks[i]->join();

        }

    };

};

 

How to use

It’s very easy to use, at the beginning you need to design an IRunnable class and implement the virtual function run(), then new a CSimpleThreadPool, start all the working thread by calling startAll(), and finally submit some task to the thread pool.

Here is the sample code:

// start all thread

void CThreadClassTestDlg::OnBnClickedButtonStart()

{

    CSimpleThreadPool *pCSimpleThreadPool = NULL;

    pCSimpleThreadPool = new CSimpleThreadPool(5);

 

    if (NULL == pCSimpleThreadPool)

        return;

 

    pCSimpleThreadPool->startAll();

 

    Increase *pIncrease = NULL;

    pIncrease = new Increase(&this->m_CEdit_counter);

    g_pCSimpleThreadPool->submit(pIncrease);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值