一个简单的线程池

 
 
话说这个线程池也写了好久了 ,做简单的东西的时候也在用,最近因为一个失误删掉了自己的一些文件导致重新写了一遍 所以贴出来,以防万一 并且跟大佬们交流
//
// Created by cxhmyself on 18-4-10.
//

#include <condition_variable> //都需要与互斥量一起才能工作
#include <mutex>
#include <queue>
#include <thread>
#include <memory>
#include "../epoll/Epoll.h"
//template <class T , class Container = std::deque<T> > // 模板的所有要定义在同一个文件里面


template<class T>
class threadsafe_queue
{
public:
    threadsafe_queue() = default;
    threadsafe_queue(const threadsafe_queue &Q)
    {
        std::lock_guard<std::mutex> lk(mut);
        dq = Q.dq;
    }
    threadsafe_queue& operator=(const threadsafe_queue & ) = delete;

    void push(const T data)
    {
        std::lock_guard<std::mutex> lk(mut);
        dq.push(data);
        cond.notify_one();
    }
    bool try_pop(T& value)
    {
        std::lock_guard<std::mutex> lk(mut);
        if( dq.empty() )
            return false;
        value = dq.front();
        dq.pop();
        return true;
    }
    std::shared_ptr<T> try_pop()
    {
        std::lock_guard<std::mutex> lk(mut);
        if( dq.empty() )
            return std::shared_ptr<T> ();
        std::shared_ptr<T> res( std::make_shared<T>(dq.front()) );
        dq.pop();
        return res;
    }

    void wait_and_pop(T& value) // 用来得到顶部数据以及线程安全
    {
        std::unique_lock<std::mutex> lk(mut);
        cond.wait(lk, [this] {return !(this->dq).empty() ; } );
        value = dq.front();
        dq.pop();
    }
    std::shared_ptr<T> wait_and_pop()
    {
        std::unique_lock<std::mutex> lk(mut);
        cond.wait(lk, [this] {return !(this->dq).empty() ; } );
        std::shared_ptr<T> result{ std::make_shared<T>(dq.front()) };
        dq.pop();
        return result;
    }

    bool empty()
    {
        std::lock_guard<std::mutex> lk(mut);
        return dq.empty();
    }
private:
    //分别是互斥量 条件变量 和队列本身
    std::queue<T> dq;
    std::mutex mut;
    std::condition_variable cond;
};

#endif

/*最简单的线程池*/

#ifndef STUDENTCHARGE_THREADPOOL_H
#define STUDENTCHARGE_THREADPOOL_H



/*思考如何加入任务 使其为一个单源*/
/*任务类 T */

template<typename T>
class Thread_pool
{
    void run()
    {
        while( !stop )
        {
            /*获取任务 要求每一个对象必须拥有一个任务执行表 即get_task()方法必须存在 使用接口的方式实现 每个必须继承之*/
            /*临时封装一个任务是为了接受不同的情况 当然这里好象是并不需要的*/
            auto item = worker_queue.try_pop();
            if( item.get() != nullptr )
            {
                /*执行任务*/
                (*(*item)).task();
                if( this->epollPoint != nullptr )
                    (*epollPoint).resetOneShot((*(*item)).getfd());
            } else {
                std::this_thread::yield();
            }
        }
    }
public:
    /*构造函数*/
    Thread_pool(Epoll *e = nullptr) :stop(false) ,epollPoint(e) {
        sum_threads = std::thread::hardware_concurrency() - 1;
        /*启动所有的线程*/
        try {
            for (int i = 0; i < sum_threads; ++i)
                thread_pool.push_back(std::thread(&Thread_pool::run, this));
        }
        catch (...)
        {
            this->~Thread_pool();
            throw ;
        }
    }
    /*析构函数*/
    ~Thread_pool()
    {
        stop = true;
        for(int i = 0 ; i < sum_threads ; ++i)
            thread_pool[i].join();
    }
    /*添加到任务队列*/
    void add_task(T tt )
    {
        this->worker_queue.push(tt);
    }
    void * getEpoll()
    {
        return this->epollPoint;
    }
private:
    /* 请求队列 这里用的智能指针是指目标用户的所有的数据 因为任务可能多样性所以先传入整体数据 队列智能指针类型 */
    threadsafe_queue< T > worker_queue;
    /*线程池*/
    std::vector<std::thread> thread_pool;
    /*检测是否线程池被销毁 被销毁则清除所有的线程*/
    bool stop;
    /*线程池数量*/
    size_t sum_threads;
    /*这个属于独特的属性*/
    Epoll * epollPoint;
};

#endif //CURRICULUMDESIGN_THREADPOOL_H


猜你喜欢

转载自blog.csdn.net/CxhMyself/article/details/80049517