当前位置:网站首页>[Muduo] poller abstract class
[Muduo] poller abstract class
2022-07-23 13:43:00 【Cx330( ͡ _ ͡ °)】
TcpServer We have an important component on , Namely The event loop (EventLoop), A thread corresponds to an event loop , One EventLoop There is a corresponding poller And a pile of channel,channel The last article is finished , The most important thing is here poller 了 .
Poller Why is it implemented as an abstract class ? because EventLoop It is impossible to call directly Epoll perhaps Poll, It uses this abstract class directly from the abstract level poller, At that time, reference different derived class objects to call its override method with the same name . It is very convenient to expand different IO Reuse capability . Namely Multiplexer .
Poller.h
#pragma once
#include "Timestamp.h"
#include "noncopyable.h"
#include <vector>
#include <unordered_map>
// As long as it is just a pointer declaration , Just make a pre declaration
class Channel;
class EventLoop;
//muduo The core of the multi-channel event distributor in the library IO Reuse module
class Poller: noncopyable
{
public:
using ChannelList = std::vector<Channel*>;
Poller(EventLoop *loop);
virtual ~Poller() = default;
// Yes epoll It's equivalent to epoll_wait
// Currently active Channel, Or interested in some events channel, need poller To take care of channel
// To all IO Reuse and retain a unified interface , Let derived classes override
virtual Timestamp poll(int timeoutMs, ChannelList *activeChannels) = 0;
// Yes epoll It's equivalent to epoll_ctl
virtual void updateChannel(Channel *channel) = 0;
// Yes epoll It's equivalent to epoll_del
virtual void removeChannel(Channel *channel) = 0;
// Judgment parameters channel Whether in the current poller among
bool hasChannel(Channel *channel) const;
// Get one of the event loops poller, It's like in our singleton mode get instance equally , Get an instance
//EventLoop You can get the default through this interface IO Specific implementation of reuse
static Poller* newDefaultPoller(EventLoop *loop);
private:
EventLoop *ownerLoop_; // Definition poller Event loop to which it belongs EventLoop
protected:
//map Of ky:sockfd value:sockfd Of channel Channel type
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 Inside tie When was the method called ? Look back
void Channel::tie(const std::shared_ptr<void> &obj)
{
tie_ = obj; // Bind to weak smart pointer and observe strong smart pointer
tied_ = true;// After binding, it will be set to true
}
/**
* @brief When change channel Indicated by fd Of events After the event ,update Responsible for poller Inside change fd The corresponding time epoll_ctl
*
* poller Where to? ? poller Follow channel It's two different modules . because epoll Do not belong to channel tube , But they are both data EventLoop Of
*
* EventLoop Contains ChannelList" That's one channel list ", And a poller
*
* therefore channel I want to Channel register fd Corresponding events cannot be done , Because it doesn't poller object , So you have to go through EventLoop To do this
*
*/
void Channel::update()
{
// adopt Channel Of EventLoop, call poller The corresponding method of , register fd Of Events event
//add code
//loop_->updateChannel(this);
}
// stay channel Of EventLoop In the container , Delete yourself
void Channel::remove()
{
//add code
// loop_->removeChannel(this);
}
//fd obtain poller After notification , The
void Channel::handleEvent(Timestamp receiveTime)
{
if(tied_)
{
std::shared_ptr<void> guard = tie_.lock();
if(guard)
{
handleEventWithhGuard(receiveTime);
}
}
else
{
handleEventWithhGuard(receiveTime);
}
}
// according to poller Notified channel Specific events that occurred , from channel Be responsible for calling specific callback operations
void Channel::handleEventWithhGuard(Timestamp receiveTime)
{
LOG_INFO("channel handleEvent revent:%d\n", revents_);
if((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN))
{
if(closeCallback_)
{
closeCallback_();
}
}
// An error occurred in the event
if(revents_ & EPOLLERR)
{
if(errorCallback_)
{
errorCallback_();
}
}
// Can read the event
if(revents_ & (EPOLLIN | EPOLLPRI))
{
if(readCallback_)
{
readCallback_(receiveTime);
}
}
if(revents_ & EPOLLOUT)
{
if(writeCallback_)
{
writeCallback_();
}
}
}Poller Static methods in a class :
static Poller* newDefaultPoller(EventLoop *loop);Why not implement it directly in Poller.cc In file ?
1. If you really implement it in Poller.cc in , Grammatically speaking, there is no problem , Why? , Because your static side is defined in this class , Of course, it should be here cc File to define the implementation . But you have to pay attention to : This is to generate a specific one IO Reuse objects , And return a pointer to the base class , So do you have to include the header file of the derived class here . You can create one here poller Instantiate the object , Is this reasonable ?
Poller* newDefaultPoller(EventLoop *loop)
{
return new EPollPoller();
}Definitely unreasonable , Because in the inheritance structure poller It belongs to the upper base class , Derived classes can only reference base class header files , The base class cannot reference the header of the derived class , So you are in this abstract base class poller Directly reference the header file of the derived class , This is a bad implementation .
I'm a base class , Your derived class contains me naturally , As an abstract , Can I go include Of each of your derived classes ? Not reality
::getenv("key") Get variables in the environment , similar json, The header file #include <stdlib.h>
We need to create a new cc file :DefaultPoller.cc
#include "Poller.h"
#include <stdlib.h>
Poller* Poller::newDefaultPoller(EventLoop *loop)
{
if(::getenv("MUDUO_USE_POLL"))
{
return nullptr; // Generate poll Example
}
else
{
return nullptr; // Generate epoll Example
}
}边栏推荐
猜你喜欢

吴恩达机器学习系列篇p31~p42

【JS高级】正则入门基础—关于你想知道的正则表达式_01

Introduction to radar part vii 1 radar and resolution

MySQL的索引事务&&JDBC编程
![[jzof] 10 Fibonacci series](/img/65/ab5b22b0879644c210abb38b0ce640.png)
[jzof] 10 Fibonacci series

SparkSQL设计及入门,220722,

Ros2 self study notes: URDF robot modeling
![[noi simulation race] I don't know which CF paper title it is (probability expectation, martingale's stop time theorem)](/img/79/46e9bf2b39fbec9ae913c4e205acdc.png)
[noi simulation race] I don't know which CF paper title it is (probability expectation, martingale's stop time theorem)

Jupyter notebook add existing virtual environment

In depth interpretation of EVM's ecological Empire
随机推荐
Uncaught (in promise) Neo4jError: WebSocket connection failure. Due to security constraints in your
【cocos creator】spine动画,监听播放结束
Charles抓包工具测试实战
In depth interpretation of EVM's ecological Empire
养老机构智能视频监控解决方案,用新技术助力养老院智慧监管
Day 11 notes
[record] golang cross platform compilation
图形管线(一)后处理阶段 alpha测试 模版测试 深度测试 混合
Wu Enda machine learning series p31~p42
SeekTiger的Okaleido有大动作,生态通证STI会借此爆发?
Day 8 notes
PHP gets the current timestamp three bit MS MS timestamp
[noi simulation race] I don't know which CF paper title it is (probability expectation, martingale's stop time theorem)
Metaapp development interview questions
Introduction to radar part vii 4 SAR system design
Google play app store may delete the overview of APP permissions and use a new combination of data security information
MySQL index transaction & JDBC programming
数据库系统原理与应用教程(052)—— MySQL 的数据完整性(十四):交叉表查询(行列转换)
Special lecture 5 combinatorial mathematics learning experience (long-term update)
Shell运算符、$((运算式))” 或 “$[运算式]、expr方法、条件判断、test condition、[ condition ]、两个整数之间比较、按照文件权限进行判断、按照文件类型进行判断