目录
类功能
类设计
类实现
编译
//Poller描述符监控类
#define MAX_EPOLLEVENTS
class Poller{
private:
int _epfd;
struct epoll_event _evs[MAX_EPOLLEVENTS];
std::unordered_map _channels;
private:
// 对epoll的直接操作
void Update(Channel *channel, int op);
bool HasChannel(Channel *Channel);
public:
Poller();
// 添加或修改监控事件
void UpdateEvent(Channel *channel);
// 移除监控
void RemoveEvent(Channel *channel);
// 开始监控, 返回活跃连接
void Poll(std::vector *active);
};
// Poller描述符监控类
#define MAX_EPOLLEVENTS 1024
class Poller
{
private:
int _epfd;
struct epoll_event _evs[MAX_EPOLLEVENTS];
std::unordered_map _channels;
private:
// 对epoll的直接操作
void Update(Channel *channel, int op)
{
// int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
int fd = channel->Fd();
struct epoll_event ev;
ev.data.fd = fd;
ev.events = channel->Events();
int ret = epoll_ctl(_epfd, op, fd, &ev);
}
// 判断一个Channel 是否已经添加了事件监控
bool HasChannel(Channel *channel)
{
auto it = _channels.find(channel->Fd());
if (it == _channels.end())
{
return false;
}
return true;
}
public:
Poller()
{
_epfd = epoll_create(MAX_EPOLLEVENTS); // 这个值大于0就行了,无用处
if (_epfd < 0)
{
ERR_LOG("EPOLL CREATE FAILED!");
abort(); // 退出程序
}
}
// 添加或修改监控事件
void UpdateEvent(Channel *channel)
{
bool ret = HasChannel(channel);
if (ret == false)
{
// 不存在则添加
_channels.insert(std::make_pair(channel->Fd(), channel));
return Update(channel, EPOLL_CTL_ADD);
}
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 *active)
{
// int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout);
int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1); // -1阻塞监控
if (nfds < 0)
{
if (errno == EINTR) // 信号打断
{
return;
}
ERR_LOG("EPOLL WAIT ERROR:%s\n", strerror(errno));
abort();
}
for (int i = 0; i < nfds; i++) // 添加活跃信息
{
auto it = _channels.find(_evs[i].data.fd); // 没找到就说明不在我们的管理之下,这是不正常的
assert(it != _channels.end());
it->second->SetREvents(_evs[i].events); // 设置实际就绪的事件
active->push_back(it->second);
}
return;
}
};
语法编译目前没问题,Poller模块与Channel模块整合在下一节介绍