就一个使用了Epoll的简易线程池:)
线程池头文件
Sesame_Pool.h
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/epoll.h>
#include<error.h>
#include<mutex>
#include<thread>
#include<condition_variable>
#include<queue>
#include<vector>
#include<iostream>
#define Port 28357
#define Ip "xx.xx.xxx.xxx"
#define Thread_Num 10
//10这个是使用的线程的数量
class Sesame_Pool{
std::vector<std::thread*>Thread_Pool;//9这个是线程池
public:
Sesame_Pool(){};
int Serv_Socket;
int Serv_Epoll_fd;
void Init();//1初始化服务器socket和调用init_threadpool
void Init_Threadpool();//2仅初始化线程池资源
void Sesame_Loop();//11
std::mutex Sesame_lock;
std::condition_variable Sesame_Cv;
//4声明线程们能共享访问的锁对象和条件变量对象
std::queue<int>Task_List;//8这个是任务队列
~Sesame_Pool();
};
void Work_Thread(int Input_Socket,Sesame_Pool* Serv);//3是工作线程
Sesame_Pool.cpp
#include"Sesame_Pool.h"
void Work_Thread(int Input_Socket,Sesame_Pool* serv){
while(1){
std::unique_lock<std::mutex>Sesame_Unique_Lock(serv->Sesame_lock);
if(!serv->Task_List.empty()){
Input_Socket=serv->Task_List.front();
serv->Task_List.pop();
Sesame_Unique_Lock.unlock();//6检测任务队列并获取任务后处理任务的时候不涉及访问共享资源不需要加锁
//7下面的是业务处理 这里只写了收到什么就反射什么
if(Input_Socket==serv->Serv_Socket){
int Cd_Socket=accept(Input_Socket,NULL,NULL);
epoll_event Cd_Epoll_Event;
Cd_Epoll_Event.events=EPOLLIN|EPOLLET|EPOLLONESHOT;
Cd_Epoll_Event.data.fd=Cd_Socket;
epoll_ctl(serv->Serv_Epoll_fd,EPOLL_CTL_ADD,Cd_Socket,&Cd_Epoll_Event);
epoll_event Ser_Epoll_Event;
Ser_Epoll_Event.events=EPOLLIN|EPOLLET|EPOLLONESHOT;
Ser_Epoll_Event.data.fd=Input_Socket;
epoll_ctl(serv->Serv_Epoll_fd,EPOLL_CTL_MOD,Input_Socket,&Ser_Epoll_Event);
//14这里使用EPOLL_CTL_MOD来重设一模一样的事件 就是重设EpolloneShot 以方便下个线程能够操作此套接字
}else{
char buf[1024];
while(1){//19
int n=recv(Input_Socket,buf,sizeof(char[1024]),0);
if(n>0){
send(Input_Socket,buf,sizeof(buf),0);
}else if(n==0){
epoll_event Cd_Epoll_Event;
Cd_Epoll_Event.events=EPOLLIN|EPOLLET|EPOLLONESHOT;
Cd_Epoll_Event.data.fd=Input_Socket;
epoll_ctl(serv->Serv_Epoll_fd,EPOLL_CTL_DEL,Input_Socket,&Cd_Epoll_Event);
break;
//16对面断开了链接 下树
}else if(n<0){
if(errno==EAGAIN){
//17代表recv已经阻塞超时了也没收到消息 重设后交给别的线程就可以
epoll_event Cd_Epoll_Event;
Cd_Epoll_Event.events=EPOLLIN|EPOLLET|EPOLLONESHOT;
Cd_Epoll_Event.data.fd=Input_Socket;
epoll_ctl(serv->Serv_Epoll_fd,EPOLL_CTL_MOD,Input_Socket,&Cd_Epoll_Event);
break;
}
}
}
}
}else{
serv->Sesame_Cv.wait(Sesame_Unique_Lock);//5无任务的时候就用条件变量使得线程沉睡
}
}
}
void Sesame_Pool::Init(){
Serv_Socket=socket(AF_INET,SOCK_STREAM,0);
if(Serv_Socket<0){
perror("socket fail");
}
sockaddr_in In;
In.sin_family=AF_INET;
In.sin_port=htons(Port);
In.sin_addr.s_addr=htonl(INADDR_ANY);
int opt=1;
setsockopt(Serv_Socket,SOL_SOCKET,SO_REUSEADDR,(const char*)&opt,sizeof(int));
if(bind(Serv_Socket,(sockaddr*)&In,sizeof(In))<0){
perror("bind fail");
}
listen(Serv_Socket,128);
Serv_Epoll_fd=epoll_create(1);
epoll_event Serv_Epoll_Event;
Serv_Epoll_Event.events=EPOLLIN|EPOLLET|EPOLLONESHOT;//12声明epoll读事件 ET工作模式 以及Epolloneshot
Serv_Epoll_Event.data.fd=Serv_Socket;
epoll_ctl(Serv_Epoll_fd,EPOLL_CTL_ADD,Serv_Socket,&Serv_Epoll_Event);
Init_Threadpool();
}
void Sesame_Pool::Init_Threadpool(){
std::thread* th;
for(int i=0;i<Thread_Num;i++){
th=new std::thread(Work_Thread,0,this);
Thread_Pool.push_back(th);
}
}
void Sesame_Pool::Sesame_Loop(){
while(1){
epoll_event* Epoll_Wait_Events;
int res=epoll_wait(Serv_Epoll_fd,Epoll_Wait_Events,128,0);
if(res>0){
for(int i=0;i<res;i++){
Task_List.push(Epoll_Wait_Events[i].data.fd);
Sesame_Cv.notify_one();//13有任务就入队列 并唤醒一个线程来处理
}
}
}
}
Sesame_Pool::~Sesame_Pool(){
for(int i=0;i<Thread_Pool.size();i++){
delete Thread_Pool[i];
}//18释放堆资源
}
调用线程池类
#include"Sesame_Pool.cpp"
int main(){
Sesame_Pool Test_Pool;
Test_Pool.Init();
Test_Pool.Sesame_Loop();
}
就酱