簡單實用C++11現實線程池

#ifndef THREAD_POOL_H
#define THREAD_POOL_H

#include <vector>
#include <queue>
#include <atomic>
#include <future>
//#include <condition_variable>
//#include <thread>
//#include <functional>
#include <stdexcept>

//線程池最大容量,應儘量設小一點
#define  THREADPOOL_MAX_NUM 16
//#define  THREADPOOL_AUTO_GROW

//線程池,可以提交變參函數或拉姆達表達式的匿名函數執行,可以獲取執行返回值
//不直接支持類成員函數, 支持類靜態成員函數或全局函數,Opteron()函數等
class ThreadPool
{
    typedef std::function<void()> Task; //定義類型
    std::vector<std::thread> _pool;          //線程池
    std::queue<Task> _tasks;            //任務隊列
    std::mutex _lock;                   //同步
    std::condition_variable _task_cv;   //條件阻塞
    std::atomic<bool> _run;     //線程池是否執行
    std::atomic<int>  _idlThrNum;  //空閒線程數量

public:
    inline ThreadPool(unsigned short size = 4)
    {
        _run = true;
        _idlThrNum = 0;
        AddThread(size);
    }

    inline ~ThreadPool()
    {
        _run=false;
        _task_cv.notify_all(); // 喚醒所有線程執行
        for (std::thread& thread : _pool) {
            //thread.detach(); // 讓線程“自生自滅”
            if(thread.joinable())
                thread.join(); // 等待任務結束, 前提:線程一定會執行完
        }
    }

public:
    int IdlCount();

    int ThreadCount();

    template<class F, class... Args>
    auto Commit(F&& f, Args&&... args)
    -> std::future<typename std::result_of<F(Args...)>::type>;

private:
    void AddThread(unsigned short size);

};

template<class F, class... Args>
auto ThreadPool::Commit(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>
{
    if (!_run)
    {
        throw std::runtime_error("Commit on ThreadPool is stopped.");
    }

    typedef typename std::result_of<F(Args...)>::type return_type;

    auto task = std::make_shared<std::packaged_task<return_type()> >(  //指向F函數的智能指針
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)  //傳遞函數進行構造
        );

    std::future<return_type> future = task->get_future();
    {    // 添加任務到隊列
        std::lock_guard<std::mutex> lock{ _lock };//對當前塊的語句加鎖  lock_guard 是 mutex 的 stack 封裝類,構造的時候 lock(),析構的時候 unlock()
        _tasks.emplace([task](){ // push(Task{...}) 放到隊列後面
            (*task)();
        });
    }

    _task_cv.notify_one(); // 喚醒一個線程執行

    return future;
}

#endif

#include "Base/ThreadPool.h"

//空閒線程數量
int ThreadPool::IdlCount()
{
    return _idlThrNum;
}

//線程數量
int ThreadPool::ThreadCount()
{
    return _pool.size();
}

void ThreadPool::AddThread(unsigned short size)
{
    for (; _pool.size() < THREADPOOL_MAX_NUM && size > 0; --size)
    {   //增加線程數量,但不超過 預定義數量 THREADPOOL_MAX_NUM
        _pool.emplace_back( [this]{ //工作線程函數
            while (_run)
            {
                Task task; // 獲取一個待執行的 task
                {
                    // unique_lock 相比 lock_guard 的好處是:可以隨時 unlock() 和 lock()
                    std::unique_lock<std::mutex> lock{ _lock };
                    _task_cv.wait(lock, [this]{
                            return !_run || !_tasks.empty();
                    }); // wait 直到有 task
                    if (!_run && _tasks.empty())
                        return;
                    task = move(_tasks.front()); // 按先進先出從隊列取一個 task
                    _tasks.pop();
                }
                _idlThrNum--;
                task();//執行任務
                _idlThrNum++;
            }
        });
        _idlThrNum++;
    }
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章