缩略版muduo网络库:事件处理器 Chanel
Posted 看,未来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缩略版muduo网络库:事件处理器 Chanel相关的知识,希望对你有一定的参考价值。
文章目录
从TcpServer开始,找到了EventLoop,在EventLoop中又找到了两个重要组成部分,Chanel和Poller,那就自底向上。
#pragma once
#include "nocopyable.hpp"
#include "timestamp.hpp"
#include <functional>
#include <memory> //智能指针需要
class EventLoop; //前置声明,避免过多的头文件包含
class Channel:nocpoyable{
public:
using EventCallback = std::function<void()>; //设置事件回调名称
using ReadEventCallback = std::function<void(timestamp)>;
Channel(EventLoop* loop,int fd); //这里只需要个指针,前置声明无伤大雅
~Channel();
//fd得到poller事件通知后,处理事件
void handleEvent(timestamp receiveTime); //这里需要初始化了,不能仅仅前置声明,需要包头文件了
//设置回调函数对象
void setReadCallback(ReadEventCallback cb){ readCallback_ = std::move(cb); }
void setWriteCallback(EventCallback cb){ writeCallback_ = std::move(cb); }
void setCloseCallback(EventCallback cb){ closeCallback_ = std::move(cb); }
void setErrorCallback(EventCallback cb){ errorCallback_ = std::move(cb); }
//防止手动remove channel之后,channel还在执行回调操作
void tie(const std::shared_ptr<void>&);
int fd() const { return fd_; }
int events() const { return events_; }
void set_revents(int revt) { revents_ = revt; }
// int revents() const { return revents_; }
bool isNoneEvent() const { return events_ == kNoneEvent; }
void enableReading() { events_ |= kReadEvent; update(); }
void disableReading() { events_ &= ~kReadEvent; update(); }
void enableWriting() { events_ |= kWriteEvent; update(); }
void disableWriting() { events_ &= ~kWriteEvent; update(); }
void disableAll() { events_ = kNoneEvent; update(); }
bool isWriting() const { return events_ & kWriteEvent; }
bool isReading() const { return events_ & kReadEvent; }
// for Poller
int index() { return index_; }
void set_index(int idx) { index_ = idx; }
//one loop per thread
EventLoop* ownerLoop() { return loop_; }
void remove();
private:
void update();
void handleEventWithGuard(timestamp receiveTime);
//事件状态标志
static const int kNoneEvent;
static const int kReadEvent;
static const int kWriteEvent;
EventLoop* loop_; // 事件循环
const int fd_; //poller监听对象
int events_; //注册fd感兴趣的事件
int revents_; //poller返回的具体发生的事情
int index_;
bool logHup_;
std::weak_ptr<void> tie_;
int tied_;
bool eventHandling_;
bool addedToLoop_;
//channel通道可以获知fd最终发生的具体时间revents,所以它负责调用具体事件的回调操作
ReadEventCallback readCallback_;
EventCallback writeCallback_;
EventCallback closeCallback_;
EventCallback errorCallback_;
};
#include"channel.hpp"
#include"eventloop.hpp"
#include"logger.hpp"
#include<sys/epoll.h>
//事件状态标志
const int kNoneEvent = 0;
const int kReadEvent = EPOLLIN | EPOLLPRI;
const int kWriteEvent = EPOLLOUT;
Channel::Channel(EventLoop* loop,int fd)
: loop_(loop),fd_(fd),events_(0),revents_(0),index_(-1),
logHup_(true),tied_(false),eventHandling_(false),addedToLoop_(false)
{
}
Channel::~Channel(){}
void Channel::tie(const std::shared_ptr<void> &obj){
tie_ = obj;
tied_ = true;
}
//当改变了channel所表示的fd的events事件后,update负责在poller中修改fd相应事件的epoll_ctl
void Channel::update(){
/*
当channel所属的EventLoop调用poller的相应方法,注册fd的events事件
add code...
*/
}
//用完了把自己咔嚓了
void Channel::remove(){
//add code...
}
void Channel::handleEvent(timestamp receiveTime){
if (tied_){ //对于tied_的在哪里被修改使用目前是个未知数
std::shared_ptr<void> guard = tie_.lock();
if (guard){
handleEventWithGuard(receiveTime);
}
}
else{
handleEventWithGuard(receiveTime);
}
}
//根据具体接收到的事件,执行相应的回调操作
void Channel::handleEventWithGuard(timestamp receiveTime){
LOG_INFO("channel handleEvent revents:%d",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_();
}
}
}
以上是关于缩略版muduo网络库:事件处理器 Chanel的主要内容,如果未能解决你的问题,请参考以下文章