在select、poll和epoll详解中提到了可以对poll和epoll进行封装,提供统一的接口。封装目的主要有两个:复用和易用,以下封装希望屏蔽poll和epoll使用时的诸多细节,提供简单易用的接口
珠玉在前,本文所提供的代码参考自muduo网络库,另外代码有用到tools-cxx中提供的base库和log库
框架
首先看一下整体类图:
PollPoller和EPollPoller分别对poll和epoll进行了封装,两者继承自Poller,Poller提供了统一的接口
Channel封装了事件分发机制,与Poller是聚合关系
Channel
Channel对象负责文件描述符事件的分发,每个Channel对象自始至终只负责一个文件描述符的事件分发,Channel对象中保存了其负责的文件描述符的事件处理函数,事件发生时会调用响应的事件处理函数。值得注意的是:Channel不持有对应的文件描述符,即不负责close
Channel.h如下,源文件见Channel.cpp [1]
#ifndef CHANNLE_H_
#define CHANNLE_H_
#include <functional>
#include "tools/base/noncopyable.h"
class Poller;
class Channel : noncopyable {
public:
Channel(Poller *poller, int fd);
~Channel() = default;
int get_fd() const {
return m_fd;
}
int get_events() const {
return m_events;
}
int get_revents() const {
return m_revents;
}
void set_revents(int revents){
m_revents = revents;
}
int get_index() const {
return m_index;
}
void set_index(int index){