Channel介绍
Channel 理解为通道,封装了sockfd和其感兴趣的event,如EPOLLIN、EPOLLOUT事件还绑定了poller返回的具体事件
EventLoop内包含poller和channel, channel中包含了fd和感兴趣的事件以及真实发生的事件,这些事件要向poller中注册,发生的事件由poller向channel通知,channel得到相应fd的事件通知后,调用相应的回调操作
Channel.h
#pragma once
#include "noncopyable.h"
#include "Timestamp.h"
#include <functional>
#include <memory>
// 类的前置声明
class EventLoop;
/*
Channel 理解为通道,封装了sockfd和其感兴趣的event,如EPOLLIN、EPOLLOUT事件
还绑定了poller返回的具体事件
EventLoop内包含poller和channel,
channel中包含了fd和感兴趣的事件以及真实发生的事件,
这些事件要向poller中注册,发生的事件由poller向channel通知,
channel得到相应fd的事件通知后,调用相应的回调操作
*/
class Channel : noncopyable{
public:
//typedef std::function<void()> EventCallback;
//C++ 11语法 using
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);}
//防止当channel被手动remove掉,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;}
// 设置fd相应的事件状态
void enableReading() {events_ |= kReadEvent; update();}
void disableReading() {events_ &= ~kReadEvent; update();}
void enableWriting() {events_ |= kWriteEvent; update();}
void disableWriting() {events_ &= ~kReadEvent; update();}
void disableAll() {events_ = kNoneEvent; update();}
// 返回fd当前的事件状态
bool isNoneEvent() const {return events_ == kNoneEvent;}
bool isWriting() const {return events_ & kWriteEvent;}
bool isReading() const {return events_ & kReadEvent;}
int index() {return index_;}
void set_index(int idx) {index_ = idx;}
// one loop per thread
EventLoop* ownerLoop() {return loop_;}
void remove();
private:
static const int kNoneEvent; //没有事件
static const int kReadEvent; // 读事件
static const int kWriteEvent; // 写事件
EventLoop *loop_; // 事件循环
const int fd_;// fd, Poller监听的对象
int events_;// 注册fd感兴趣的事件
int revents_;// poller返回的具体发生的事件
int index_;
std::weak_ptr<void> tie_;
bool tied_;
// 因为Channel通道里能够获知fd最终发生的具体的事件revents,所以它负责调用具体事件的回调操作
ReadEventCallback readCallback_;
EventCallback writeCallback_;
EventCallback closeCallback_;
EventCallback errorCallback_;
void update();
void handleEventWithGuard(Timestamp receiveTime);
};
Channel.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(){
}
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...
// loop_ ->updateChannel(this);
}
// 在channel所属的EventLoop中,把当前的channel删除掉
void Channel::remove(){
//add code..
//loop_->removeChannel(this);
}
void Channel::handleEvent(Timestamp receiveTime) {
if (tied_) {
std::shared_ptr<void> guard = tie_.lock();
if(guard) {
handleEventWithGuard(receiveTime);
}
}else {
handleEventWithGuard(receiveTime);
}
}
//根据poller通知的channel发生的具体事件,有channel负责调用具体的回调操作
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);
}
}
}