当前位置:网站首页>【MUDUO】Poller抽象类
【MUDUO】Poller抽象类
2022-07-23 06:27:00 【Cx330( ͡ _ ͡°)】
TcpServer上有我们一个重要的组件,就是事件循环(EventLoop),一个线程对应着一个事件循环,一个EventLoop里边对应着就是一个poller 和一堆的channel,channel上一篇实现完了,最重要的就是这儿的poller了。
Poller为甚么实现成抽象类?因为EventLoop不可能直接的去调用Epoll或者Poll,它是从抽象层面直接使用了这个抽象类poller,到时候引用不同的派生类对象调用它的同名覆盖方法。就可以非常方便的去扩展不同的IO复用能力了。就是多路分发器.
Poller.h
#pragma once
#include "Timestamp.h"
#include "noncopyable.h"
#include <vector>
#include <unordered_map>
//只要是只是指针声明,就只做前置声明就可以
class Channel;
class EventLoop;
//muduo库中多路事件分发器的核心IO复用模块
class Poller: noncopyable
{
public:
using ChannelList = std::vector<Channel*>;
Poller(EventLoop *loop);
virtual ~Poller() = default;
//对epoll来说相当于epoll_wait
//当前激活的Channel,或者说是对某些事件感兴趣的channel,需要poller去照顾的channel
//给所有IO复用保留统一的接口,让派生类去重写
virtual Timestamp poll(int timeoutMs, ChannelList *activeChannels) = 0;
//对epoll来说相当于epoll_ctl
virtual void updateChannel(Channel *channel) = 0;
//对epoll来说相当于epoll_del
virtual void removeChannel(Channel *channel) = 0;
//判断参数channel是否在当前的poller当中
bool hasChannel(Channel *channel) const;
//获取到这个事件循环的一个poller,这就像我们单例模式中的get instance一样,获取一个实例
//EventLoop可以通过这个接口获取到默认的IO复用的具体实现
static Poller* newDefaultPoller(EventLoop *loop);
private:
EventLoop *ownerLoop_; //定义poller所属的事件循环EventLoop
protected:
//map的ky:sockfd value:sockfd所属的channel通道类型
using ChannelMap = std::unordered_map<int, Channel*>;
ChannelMap channels_;
};
Poller.cc
#include "Channel.h"
#include "EventLoop.h"
#include "Logger.h"
#include <sys/epoll.h>
const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent = EPOLLOUT;
Channel::Channel(EventLoop *loop, int fd)
:loop_(loop),fd_(fd),events_(0),revents_(0),index_(-1),tied_(false)
{}
Channel::~Channel(){}
//channel里的tie方法什么时候被调用过? 后边再看
void Channel::tie(const std::shared_ptr<void> &obj)
{
tie_ = obj; //绑定成弱智能指针观察强智能指针
tied_ = true;//绑定过了就置成true
}
/**
* @brief 当改变channel所表示fd的events事件后,update负责在poller里面更改fd相应的时间epoll_ctl
*
* poller在哪呢? poller 跟channel是两个不同的模块。因为epoll不属于channel管,但是他们两都是数据EventLoop的
*
* EventLoop 包含了ChannelList"也就是一个channel列表", 和一个poller
*
* 所以channel本身想向Channel注册fd对应的事件是做不了的,因为它又没有poller对象,所以需要通过EventLoop来做这件事情
*
*/
void Channel::update()
{
//通过Channel所属的EventLoop,调用poller的相应方法,注册fd的Events事件
//add code
//loop_->updateChannel(this);
}
//在channel所属的EventLoop中的容器,把自己给删除掉
void Channel::remove()
{
//add code
// loop_->removeChannel(this);
}
//fd得到poller通知以后,处理事件的
void Channel::handleEvent(Timestamp receiveTime)
{
if(tied_)
{
std::shared_ptr<void> guard = tie_.lock();
if(guard)
{
handleEventWithhGuard(receiveTime);
}
}
else
{
handleEventWithhGuard(receiveTime);
}
}
//根据poller通知的channel发生的具体事件,由channel负责调用具体的回调操作
void Channel::handleEventWithhGuard(Timestamp receiveTime)
{
LOG_INFO("channel handleEvent revent:%d\n", revents_);
if((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN))
{
if(closeCallback_)
{
closeCallback_();
}
}
//事件发生错误
if(revents_ & EPOLLERR)
{
if(errorCallback_)
{
errorCallback_();
}
}
//可读事件
if(revents_ & (EPOLLIN | EPOLLPRI))
{
if(readCallback_)
{
readCallback_(receiveTime);
}
}
if(revents_ & EPOLLOUT)
{
if(writeCallback_)
{
writeCallback_();
}
}
}Poller类中的静态方法:
static Poller* newDefaultPoller(EventLoop *loop);为什么不直接实现在Poller.cc文件中?
1.如果你真的把它实现在Poller.cc中,从语法上来说没有任何问题,为什么,因为你这个静态方是在这个类里边定义的,那理所当然的就应该在这个cc文件中去定义实现。但是你要注意:这个可是要生成一个具体的一个IO复用对象,并返回一个基类的指针,所以你在这里是不是一定要包含了派生类的头文件。你才能在这去创建一个poller的实例化对象,那么请问这个合理吗?
Poller* newDefaultPoller(EventLoop *loop)
{
return new EPollPoller();
}肯定不合理的,因为在继承结构中poller属于上基类,派生类只能引用基类头文件,而基类不能引用派生类的问头件,所以你在这个抽象的基类poller中直接去引用派生类的的头文件,这是一个不好的实现。
我是基类,你们派生类包含我天经地义,我作为抽象,我能不能去include的你们的每个派生类?不现实
::getenv("key") 获取环境中的变量,类似json, 头文件#include <stdlib.h>
我们需要新创建一个cc文件:DefaultPoller.cc
#include "Poller.h"
#include <stdlib.h>
Poller* Poller::newDefaultPoller(EventLoop *loop)
{
if(::getenv("MUDUO_USE_POLL"))
{
return nullptr; //生成poll的实例
}
else
{
return nullptr; //生成epoll的实例
}
}边栏推荐
- Google Play应用商店可能会删除应用权限概述 转而使用新的数据安全信息组合
- -XX:+UseCGroupMemoryLimitForHeap 无法创建虚拟机问题
- [visual scheduling software] Shanghai daoning brings netronic downloads, trials and tutorials to SMB organizations
- [jzof] 08 next node of binary tree
- PHP framework MVC class code audit
- Google面试题原理解析 12个乒乓球其中有1个次品,用天平称重3次找出
- UI自动化
- Knowledge map: basic concepts
- Intercept the specified range data set from list < map >
- JVM详细解析
猜你喜欢

行业现状令人失望,工作之后我又回到UC伯克利读博了

Beifu PLC and C transmit bool array variables through ads communication

编译与预处理

射击游戏 第 1-2 课:使用精灵

What is the reason for the failure of video playback and RTMP repeated streaming on easygbs platform?

分类模型的评估

Numpy: quick start to basic operations

Day 10 notes

Talk about study and work -- Qian Xuesen

太空射击 Part 2-3: 子弹与敌人碰撞处理
随机推荐
倍福PLC和C#通过ADS通信传输String类型
Functional testing to automated testing, sharing ten years of automated testing experience
Numpy: element selection of matrix
C language insert sort (direct insert sort)
Space shooting part 1: player spirit and control
Day 10 notes
Is it safe to open an account with Guosen Securities software? Will the information be leaked?
Talk about study and work -- Qian Xuesen
倍福PLC和C#通过ADS通信传输结构体类型变量
High voltage MOS tube knx42150 1500v/3a is applied to frequency converter power supply inverter, etc
Bit synchronization process of CAN controller
【可視化調度軟件】上海道寧為SMB組織帶來NETRONIC下載、試用、教程
Intercept the specified range data set from list < map >
射击 第 1-01 课:入门
MySQL----复合查询 外连接
Problem solving: script file 'scripts\pip script py‘ is not present.
Netease white hat hacker training camp notes (2)
倍福PLC和C#通过ADS通信传输String数组类型变量
【 Visual Dispatching Software】 Shanghai Dow Ning apporte netronic download, Trial, tutoriel pour l'Organisation SMB
Notes on the ninth day