前面几篇博客介绍了Epoll, ThreadPool,

其中 Epoll 封装了epoll的各类api, 可在epoll句柄中添加/修改/删除 fd 的 各类事件(EPOLLIN | EPOLLOUT), 可以返回一个 active的事件集合,并提供了一个回调函数指针,统一处理这些事件。

ThreadPool 则封装了一个任务队列,一个线程vector, 可以网线程池添加任务,并新建线程从任务队列取出任务执行。

这一篇将结合前面的Epoll和ThreadPool, 实现一个事件管理器,使用Epoll 添加和监听 fd 的 可读或可写事件,注册统一的事件处理接口来处理active的事件集合,将该回调函数放进任务队列,通知并等待线程池分配线程处理,统一的事件处理接口里则通过查询一个fd, callback的map, 找到对应fd的callback, 并加进任务队列,通知并等待线程池新建或者分配线程来处理。事件处理器每次添加或者修改fd的事件时,都会更新相应的fd, callback 的map, 以备后续回调时查询使用。

#include "Epoll.h"
#include "ThreadPool.h"
#include<iostream> class EventManager{
public:
EventManager( int thread_pool_size );
EventManager( const EventManager& ) = delete;
EventManager& operator=( const EventManager& ) = delete;
~EventManager(); void SetThreadPoolSize( size_t size ) ;
size_t Size(); void AddTask( Base::Closure* task );
int AddTaskWaitingReadable( int fd, Base::Closure* task );
int AddTaskWaitingWritable( int fd, Base::Closure* task );
int RemoveAwaitingTask( int fd );
int ModifyTaskWaitingStatus( int fd, int status, Base::Closure* task ); void Start();
void AwaitTermination();
void Stop(); void EpollAwakeHandler( const Epoll::ActiveEvents* ); private:
FixedThreadPool thread_pool_;
Epoll epoll_;
std::map<int, Base::Closure*> inactive_tasks_map_;
std::mutex mutex_;
}; EventManager::EventManager(int thread_pool_size) {
// Create at least 3 working threads. One of them is epolling thread.
if (thread_pool_size < 3) {
thread_pool_size = 3;
}
thread_pool_.SetPoolSize(thread_pool_size);
} EventManager::~EventManager() {
std::cout << "deleting event manager" << std::endl;
} void EventManager::SetThreadPoolSize(size_t size) {
std::unique_lock<std::mutex> lock(mutex_);
thread_pool_.SetPoolSize(size);
} size_t EventManager::Size() {
std::unique_lock<std::mutex> lock(mutex_);
return thread_pool_.Size();
} // 将StartPolling (epoll_wait)作为一个任务,单独一个线程执行
// 先监听得到待处理的fd和事件的集合,再调用事件统一处理接口EpollAwakeHandler来对监听到的fd及事件进行处理,其处理过程是通过查map,将fd对应的回调函数加入任务队列,等待线程池分配线程
// 进行处理。
void EventManager::Start() {
// Set awake callback for epoll.
epoll_.SetAwakeCallBack(new Epoll::EpollAwakeCallBack(
std::bind(&EventManager::EpollAwakeHandler, this, std::placeholders::_1))); // 用EventManager::EpollAwakeHandle函数来初始化Epoll里的回调函数,在执行Epoll::StartPolli // ng的时候,先epoll_wait监听得到fd和事件集合,再调用该回调函数处理发生的事件。
// First add epolling thread to work.
thread_pool_.AddTask(Base::NewCallBack(&Epoll::StartPolling, &epoll_)); //新建一个线程来执行任务, 把 StartPolling 放入任务队列,notify_one 一个线程来执行StartPolling 任务 // Start the internal thread poll.
thread_pool_.Start(); // 开启线程池
} // 将监听到的事件fd集合作为参数传入EventManager::EpollAwakeHandler, 遍历事件集合,在inactive_tasks_map_里根据fd关键字查找对应的回调函数,
//如果能找到,就将该回到函数加入到任务队列,之后会有某个线程来执行
// EventManager::EpollAwakeHandler 相当于是一个事件处理的统一接口,封装了基于线程池对不同事件的不同处理过程
void EventManager::EpollAwakeHandler(const Epoll::ActiveEvents* active_events) {
std::unique_lock<std::mutex> lock(mutex_);
for (auto i = 0; i < active_events->num(); i++) {
int fd = active_events->events()[i].data.fd;
if (inactive_tasks_map_.find(fd) != inactive_tasks_map_.end()) {
//std::cout << "find task on fd " << fd << std::endl;
thread_pool_.AddTask(inactive_tasks_map_[fd]);
}
}
} void EventManager::AddTask(Base::Closure* task) {
thread_pool_.AddTask(task);
} // 在epoll句柄中添加了一个需要监听可读事件的描述符,并更新了inactive_tasks_map_中的该fd对应的回调函数
int EventManager::AddTaskWaitingReadable(int fd, Base::Closure* task) {
std::unique_lock<std::mutex> lock(mutex_);
int ret = epoll_.AddMonitorReadableEvent(fd); // 监听该fd上是否有可读事件发生,且只监听一次,当这次监听完成后, 如果还需要继续监听这个fd, 需要再次加入
if (ret) { // 成功返回0, 失败返回-1
return ret;
}
if (inactive_tasks_map_.find(fd) != inactive_tasks_map_.end()) { // 如果能在inactive_tasks_map_里找到该fd对应的回调函数,就先删除掉,然后再为该fd添加新的回调函数
delete inactive_tasks_map_[fd];
}
inactive_tasks_map_[fd] = task;
return 0;
}
// 在epoll句柄中添加了一个需要监听可写事件的描述符,并更新了inactive_tasks_map_中的该fd对应的回调函数
int EventManager::AddTaskWaitingWritable(int fd, Base::Closure* task) {
std::unique_lock<std::mutex> lock(mutex_);
int ret = epoll_.AddMonitorWritableEvent(fd);
if (ret) {
return ret;
}
if (inactive_tasks_map_.find(fd) != inactive_tasks_map_.end()) {
delete inactive_tasks_map_[fd];
}
inactive_tasks_map_[fd] = task;
return 0;
} int EventManager::RemoveAwaitingTask(int fd) {
std::unique_lock<std::mutex> lock(mutex_);
int ret = epoll_.DeleteMonitoringEvent(fd); // 在epoll句柄中删除了该fd以及该fd要监听的可读事件
if (ret) {
return ret;
}
if (inactive_tasks_map_.find(fd) != inactive_tasks_map_.end()) { // 并在inactive_tasks_map_中删除掉该项key-value对
delete inactive_tasks_map_[fd];
inactive_tasks_map_.erase(inactive_tasks_map_.find(fd));
}
return 0;
}
// 修改该fd需要监听的事件,并更新inactive_tasks_map_中该fd对应的回调函数
int EventManager::ModifyTaskWaitingStatus(int fd, int status, Base::Closure* task) {
std::unique_lock<std::mutex> lock(mutex_);
int ret = epoll_.ModifyMonitorEvent(fd, status);
if (ret) {
return ret;
}
if (inactive_tasks_map_.find(fd) != inactive_tasks_map_.end()) {
delete inactive_tasks_map_[fd];
}
inactive_tasks_map_[fd] = task;
return 0;
} void EventManager::AwaitTermination() {
thread_pool_.AwaitTermination();
} void EventManager::Stop() {
thread_pool_.Stop();
} int main(){
EventManager em(4); return 0; }

最新文章

  1. UNIX进程
  2. transform应用详解
  3. VC++ TinyXML
  4. adb或appium下多设备中指定设备的启动
  5. UVa 10250 The Other Two Trees
  6. HDU 5694 BD String 递归暴力
  7. Char Varchar Nvarchar区别
  8. VM下Linux网卡丢失(pcnet32 device eth0 does not seem to be ...)解决方案
  9. 在shell中运行以不同方式运行脚本
  10. [HNOI2010]弹飞绵羊
  11. 二叉树最近公共祖先(LeetCode)
  12. MySQL、MariaDB修改默认字符集
  13. eclipse显示代码行数
  14. [No0000179]改善C#程序的建议2:C#中dynamic的正确用法
  15. 关于Object.prototype.toString.call
  16. a标签自执行点击事件
  17. TCP/IP三次握手与四次挥手
  18. TortoiseGit使用笔记
  19. tcp端口检测
  20. YARN的重启动问题:RM Restart/RM HA/Timeline Server/NM Restart

热门文章

  1. 用swift开发framework时采用OC混编的解决方案
  2. 20_webpack_shimming预支全局变量和css的抽离
  3. iptables( &lt; deb ufw)
  4. (0502)《UVM》sequence
  5. 2022强网拟态 WHOYOUARE
  6. ES6-Promise下
  7. 调度器30—调度相关结构体—p-&gt;flags
  8. C++的switch/case,需要大括号
  9. springboot返回前端对象null转为空字符串
  10. JAVA仓库管理系统(附源码+调试)