一、Channel模块用于事件管理
成员变量:
描述符
使用uint32_t 类型来表示需要监控的事件
使用uint32_t类型来表示当前链接触发的事件
可读事件被触发的回调函数
可写事件被触发的回调函数
错误事件被触发的回调函数
链接断来事件被触发的回调函数
任意事件被触发的回调函数

成员函数
返回文件描述符
返回想要监控的事件

设置当前链接出发的事件
设置可读事件 可读事件被触发的回调函数 可写事件被触发的回调函数 错误事件被触发的回调函数 链接断来事件被触发的回调函数 任意事件被触发的回调函数

是否监控了可读 是否监控了可写

启动读事件和写事件 关闭写事件和读事件监控

移除和更新具体需要其他模块支持

监控触发事件

全部代码
cpp
class Channel
{
private:
uint32_t _events;
uint32_t _revents;
int _fd;
EventLoop *_loop;
using EventCallBack = std::function<void()>;
EventCallBack _read_callback;
EventCallBack _write_callback;
EventCallBack _error_callback;
EventCallBack _close_callback;
EventCallBack _event_callback;
public:
Channel(EventLoop *loop, int fd) : _fd(fd), _loop(loop), _events(0), _revents(0)
{
}
uint32_t Event()
{
return _events;
}
int Fd()
{
return _fd;
}
void SetEvent(uint32_t events)
{
_revents = events;
}
void SetReadCallback(const EventCallBack &cd)
{
_read_callback = cd;
}
void SetWriteCallback(const EventCallBack &cd)
{
_write_callback = cd;
}
void SetErrorCallback(const EventCallBack &cd)
{
_error_callback = cd;
}
void SetCloseCallback(const EventCallBack &cd)
{
_close_callback = cd;
}
void SetEventCallback(const EventCallBack &cd)
{
_event_callback = cd;
}
bool ReadAble() // 是否监控了可读
{
return _events & EPOLLIN;
}
bool WriteAble()
{
return _events & EPOLLOUT;
}
void EnableRead() // 启动读事件监控
{
_events |= EPOLLIN;
Update();
}
void EnableWrite()
{
_events |= EPOLLOUT;
Update();
}
void DisableRead()
{
_events &= ~EPOLLIN;
Update();
}
void DisableWrite()
{
_events &= ~EPOLLOUT;
Update();
}
void DisableAll()
{
_events = 0;
Update();
}
void Remove();
void Update();
// 事件处理 一旦链接接触了事件,就调用了这个函数,自己触发什么自己决定
void HandleEvents()
{
if (_revents & EPOLLIN || _revents & EPOLLRDBAND || _revents & EPOLLPRI)
{
if (_read_callback)
_read_callback();
}
if (_revents & EPOLLOUT)
{
if (_event_callback)
_event_callback();
if (_write_callback)
_write_callback();
}
else if (_revents & EPOLLERR)
{
if (_error_callback)
_error_callback();
}
else if (_revents & EPOLLHUP)
{
if (_close_callback)
_close_callback();
}
if (_event_callback)
_event_callback();
}
};
Poller
采用epoll进行监听
成员变量:
文件描述符
监听就绪数组
建立文件描述符和Channel的关系变找到该文件描述符是否存在添加了事件监控

成员函数:
创造一个epoll

更新监控

判断一个Channel是否已经添加了事件监控

移除监控

开始监控并返回活跃链接

全部代码
cpp
#define MAX_EPOLLEVENTS 1024
class Poller
{
private:
int _epfd;
std::unordered_map<int, Channel *> _channels;
struct epoll_event _evs[MAX_EPOLLEVENTS];
void Update(Channel *channel, int op)
{
int fd = channel->Fd();
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.data.fd = fd;
ev.events = channel->Event();
int ret = epoll_ctl(_epfd, op, fd, &ev);
if (ret < 0)
{
ERR_LOG("EPOLLCTL FAILED! errno: %d, %s", errno, strerror(errno));
abort();
}
return;
}
public:
Poller()
{
_epfd = epoll_create(MAX_EPOLLEVENTS);
if (_epfd < 0)
{
ERR_LOG("EPOLL_CREATE FAILED");
abort();
}
}
bool HasChannel(Channel *channel)
{
auto it = _channels.find(channel->Fd());
if (it == _channels.end())
{
return false;
}
return true;
}
// 修改添加事件监控
void UpdateEvent(Channel *channel)
{
if (HasChannel(channel) == false)
{
Update(channel, EPOLL_CTL_ADD);
_channels.insert(std::make_pair(channel->Fd(), channel));
return;
}
return Update(channel, EPOLL_CTL_MOD);
}
void RemoveEvent(Channel *channel)
{
auto it = _channels.find(channel->Fd());
if (it != _channels.end())
{
_channels.erase(it);
}
Update(channel, EPOLL_CTL_DEL);
}
void Poll(std::vector<Channel *> *active)
{
int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
if (nfds < 0)
{
if (errno == EINTR)
{
return;
}
ERR_LOG("EPOLL_WAIT FAILED");
abort();
}
for (int i = 0; i < nfds; i++)
{
auto it = _channels.find(_evs[i].data.fd);
assert(it != _channels.end());
it->second->SetEvent(_evs[i].events);
active->push_back(it->second);
}
}
};