前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >缩略版muduo网络库(2):事件处理器 Chanel

缩略版muduo网络库(2):事件处理器 Chanel

作者头像
看、未来
发布2021-10-09 15:33:16
2530
发布2021-10-09 15:33:16
举报

文章目录

从TcpServer开始,找到了EventLoop,在EventLoop中又找到了两个重要组成部分,Chanel和Poller,那就自底向上。

代码语言:javascript
复制
#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_;

    
};
代码语言:javascript
复制
#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_();
        }
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档