C++11新特性,手写线程池

1、线程池

        一种基于池化思想管理和使用线程的机制,将多个线程预先储存在池子里,当有任务出现时可以避免重新创造和销毁线程所带来的性能开销。

2、IO模型

1)阻塞IO模型: 应用程序的进程发起IO调用,如果内核数据没有准备好 ,应用进程一直阻塞等待,直到内核数据准备好了,从内核态拷贝到用户态,才返回成功提示。

2)非阻塞IO模型:应用程序的进程发起IO调用,如果内核数据没有准备好,就返回错误信息,用户进程无需等待,而是通过轮询的方式等待请求结果,数据准备好,从内核缓冲区拷贝到用户区,返回成功提示;

3)IO多路复用

  系统提供一类可以同时监控多个fd文件描述符的函数epoll、select、poll,任何一个返回内核数据就绪,应用进程再发起系统调用。 

4)信号驱动IO

    用户进程向内核发送一个信号,  不用阻塞,当内核数据准备好后,在通过信号通知应用进程数据可读,应用进程收到信号后立即去处理。

5)异步IO模型

应用进程发出系统调用后,立刻返回提交成功的提示,等待内核数据处理好将数据拷贝到用户缓冲区后,发送信号通知用户进程IO操作执行完毕。aio_read和aio_write

3、事件处理模式

1)reactor

  • 主线程往epoll内核事件表中注册socket的读就绪事件
  • 主线程调用epoll_wait等待socket上有数据可读
  • 当socket上有数据可读时,epoll_wait通知主线程,主线程将可读事件放入请求队列
  • 睡眠在请求队列上的某个工作线程被唤醒,从socket读取数据,并处理客户请求,然后往epoll内核事件表中注册该socket上的写就绪事件
  • 主线程调用epoll_wait等待socket可写
  • 当socket可写时,epoll_wait通知主线程,主·线程将可写事件放入请求队列
  • 睡眠在请求队列上的工作线程被唤醒,往socket上写入服务器处理客户端请求的结果

2)preactor 

  • 主线程调用epoll内核事件表注册socket上的读就绪事件;
  • 主线程调用epoll_wait等待socket上有数据可读
  • 当socket上有数据可读时,epoll_wait通知主线程,主线程从socket上循环上读取数据,将读取的数据封装成一个请求对象并插入请求队列
  • 睡眠在请求队列上的工作线程被唤醒,它获取请求对象并处理客户请求,然后往epoll内核事件表中注册该socket上的写就绪事件;
  • 主线程调用epoll_wait等待socket可写;
  • 当socket上有数据可写时,epoll_wait通知主线程,主线程往socket上写入服务器处理请求的结果。

4、locker.h

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
//锁类
class locker
{
public:
    locker(){
        if(pthread_mutex_init(&m_mutex,NULL)!=0)
        {
            throw std::exception();
        }
    }
    ~locker(){
        pthread_mutex_destroy(&m_mutex);
    }
    bool lock(){
        return pthread_mutex_lock(&m_mutex)==0;
    }
    bool unlock(){
        return pthread_mutex_unlock(&m_mutex)==0;
    }
    //获取锁
    pthread_mutex_t *get(){
        return &m_mutex;
    }
private:
    pthread_mutex_t m_mutex;
};
//条件变量类
class cond
{
public:
    cond(){
        if(pthread_cond_init(&m_cond,NULL)!=0){
            throw std::exception();
        }
    }
    ~cond(){
        pthread_cond_destroy(&m_cond);
    }
    bool wait(pthread_mutex_t *m_mutex){
        int ret=0;
        ret=pthread_cond_wait(&m_cond,m_mutex);
        return ret==0;
    }
    bool timewait(pthread_mutex_t *m_mutex,struct timespec t){
        int ret=0;
        ret=pthread_cond_timedwait(&m_cond,m_mutex,&t);
        return ret==0;
    }
    bool broadcast(){
        return pthread_cond_broadcast(&m_cond)==0;
    }
private:
    pthread_cond_t m_cond;
};

//信号量类
class sem{
public:
    sem(){
        if(sem_init(&m_sem,0,0)!=0){
            throw std::exception();
        }
    }
    ~sem(){
        sem_destroy(&m_sem);
    }
    bool wait(){
        return sem_wait(&m_sem)==0;
    }
    bool post(){
        return sem_post(&m_sem)==0;
    }
private:
    sem_t m_sem;
};
#endif

  5、threadpool.h

#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <list>
#include <cstdio>
#include <exception>
#include <pthread.h>
#include "locker.h"
#include <stdio.h>
#include <cstdio>

template<typename T>
class threadpool
{
public:
    threadpool(int thread_number=8;int max_requests=10000);
    ~threadpool();
    bool append(T *request);
private:
    static void* worker(void *arg);//共有线程工作函数
    void run();//私有线程工作函数
private:
    int m_thread_number;//线程池中的线程数量
    pthread_t *m_threads;//线程池数组
    int m_max_requests;//请求队列中,最多允许的等待请求数量
    std::list<T*> m_workqueue;//请求队列
    locker m_queuelocker;//保护请求队列的互斥锁
    sem m_queuestat;//请求队列的信号量
    bool m_stop;//是否结束线程标志位
};

template<typename T>
threadpool<T>::threadpool(int thread_number,int max_requests):
    m_thread_number(thread_number),m_max_requests(max_requests),
    m_stop(false),m_thread(NULL){
        if((thread_number<=0)||(max_requests<=0)){
            throw std::exception();
        }
        m_threads=new pthread_t[m_thread_number];
        if(!m_threads){
            throw std::exception();
        }
        for(int i=0;i<thread_number;++i){
            printf("create the %dth thread\n",i);
            if(pthread_create(m_thread+i,NULL,worker,this)!=0){
                delete[] m_threads;
                throw std::exception();
            }
            if(pthread_detach(m_thread[i])){
                delete[] m_threads;
                throw std::exception();
            }
        }
    }

template<typename T>
threadpool<T>::~threadpool()
{
    delete[] m_threads;
    m_stop=true;
}

template<typename T>
bool threadpool<T>::append(T *request){
    m_queuelocker.lock();
    if(m_workqueue,size()>m_max_requests)
    {
        m_queuelocker.unlook();
        return false;
    }
    m_workqueue.push_back(request);
    m_queuelocker.lock();
    m_queuelocker.post();
    return true;
}

template<typename T>
void* threadpool<T>::worker(void *arg){
    threadpool *pool=(threadpool *)arg;
    pool->run();
    return pool;
}

template<typename T>
void threadpool<T>::run(){
    while (!m_stop)
    {
        m_queuestat.wait();
        m_queuelocker.lock();
        if(m_workerqueue.empty()){
            m_queuelocker.unlook();
            continue;
        }
        T* request=m_workqueue.front();
        m_workqueue.pop_front();
        m_queuelocker.unlock();
        if(!request){
            continue;
        }
        request->process();
    }
    
}

#endif

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值