加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
EpollPoller.cc 3.63 KB
一键复制 编辑 原始数据 按行查看 历史
TheSea 提交于 2024-10-07 11:34 . 完成了EpollPoller的部分
#include "EpollPoller.h"
#include "Logger.h"
#include "Channel.h"
#include <errno.h>
#include <unistd.h>
#include <strings.h>
//注意:channel的成员index_初始化时就为-1
const int kNew = -1; //表示Channel还没有添加到epoll里
const int kAdded = 1; //表示Channel已经添加到epoll里
const int kDeleted = 2; //表示Channel已经从epoll里删除了
EpollPoller::EpollPoller(EventLoop* loop)
:Poller(loop)
,epollFd_(::epoll_create1(EPOLL_CLOEXEC))
,events_(kInitEventListSize){ //vector<epoll_event>
if(epollFd_ < 0){
LOG_FATAL("epoll_create1 error:%d \n",errno);
}
}
EpollPoller::~EpollPoller(){
::close(epollFd_);
}
Timestamp EpollPoller::poll(int timeoutMs, ChannelList* activeChannels){
//实际上使用LOG_DEBUG输出日志更为合理,因为高并发场景下这里的日志会被频繁打印的
LOG_INFO("func=%s => fd total count:%lu \n", __FUNCTION__, channels_.size());
int numEvents = ::epoll_wait(epollFd_,&*events_.begin(),static_cast<int>(events_.size()),timeoutMs);
int savedErrno = errno;
Timestamp now(Timestamp::now());
if(numEvents > 0){
LOG_INFO("%d events happened \n",numEvents);
fillActiveChannels(numEvents,activeChannels);
if(numEvents == events_.size()){ //如果发现全部都有监听消息发生,那么就应该进行扩容了
events_.resize(events_.size()*2);
}
}
else if(numEvents == 0){
LOG_DEBUG("%s timeout! \n", __FUNCTION__);
}
else{
if(savedErrno != EINTR){
errno = savedErrno;//muduo源码中需要访问全局变量errno,因此源码中这里又赋值回去了
LOG_ERROR("EpollPoller::poll() error!");
}
}
return now;
}
void EpollPoller::updateChannel(Channel* channel){
const int index = channel->index();
LOG_INFO("func=%s => fd=%d events=%d index=%d \n", __FUNCTION__, channel->fd(), channel->events(), index);
//要么是从来没添加过现在要添加,要么是之前被删除了现在又想添加
if(index == kNew || index == kDeleted){
if(index == kNew){
int fd = channel->fd();
channels_[fd] = channel;
}
channel->set_index(kAdded);
update(EPOLL_CTL_ADD,channel);
}
else{ //否则channel已经在poller上注册过了
int fd = channel->fd();
if(channel->isNoneEvent()){ //如果是对所有事件都不感兴趣了,那就删除
update(EPOLL_CTL_DEL,channel);
channel->set_index(kDeleted);
}
else{//否则就是进行修改
update(EPOLL_CTL_MOD,channel);
}
}
}
//从Poller中删除channel
void EpollPoller::removeChannel(Channel* channel){
int fd = channel->fd();
channels_.erase(fd);
LOG_INFO("func=%s => fd=%d \n", __FUNCTION__, fd);
int index = channel->index();
if(index == kAdded){
update(EPOLL_CTL_DEL,channel);
}
channel->set_index(kNew);
}
//填写活跃的连接
void EpollPoller::fillActiveChannels(int numEvents,ChannelList* activeChannels) const{
for(int i=0; i<numEvents; ++i){
Channel* channel = static_cast<Channel*>(events_[i].data.ptr);
channel->set_revents(events_[i].events);
activeChannels->push_back(channel); //EventLoop就拿到了它的poller给它返回的所有发生事件的channel列表了
}
}
//更新Channel通道
void EpollPoller::update(int operation, Channel* channel){
struct epoll_event event;
bzero(&event, sizeof event);
int fd = channel->fd();
event.events = channel->events();
event.data.fd = fd;
event.data.ptr = channel;
if(::epoll_ctl(epollFd_,operation,fd,&event) < 0){
if(operation == EPOLL_CTL_DEL){
LOG_ERROR("epoll_ctl_del error: %d \n",errno);
}
else{
LOG_FATAL("epoll_ctl_add/mod error: %d \n",errno);
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化