Channel扮演了一个IO事件分发器的作用。主要有两个地方,一个是Acceptor中的Channel,主要处理连接事件,另外每个TcpConnection类中会有一个Channel,检测fd的刻可读,关闭,错误消息,触发相应的回调函数。生命周期由Acceptor和TcpConnection控制。
成员变量:
private:static const int kNoneEvent;static const int kReadEvent;static const int kWriteEvent;EventLoop* loop_;const int fd_;int events_;int revents_; int index_; bool logHup_;std::weak_ptr<void> tie_; bool tied_;//bool eventHandling_;//bool addedToLoop_;ReadEventCallback readCallback_;EventCallback writeCallback_;EventCallback closeCallback_;EventCallback errorCallback_;
kNoneEvent,KreadEvent,kWriteEvent是用于标记events_状态的值,loop是传入的所属的eventloop,fd_是创建通道时传入的文件描述符,events_是通道状态标记,revents_是多路复用检测后外部set的事件类型,tie用于延长对象的生命周期,readCallback,writeCallback,closeCallback,errorCallback则是注册的外部回调。
重要函数及作用:
创建
Channel::Channel(EventLoop* loop, int fd__): loop_(loop),fd_(fd__),events_(0),revents_(0),index_(-1),logHup_(true),tied_(false)/*,eventHandling_(false),addedToLoop_(false)*/
{
}
因为一般网络库会把监听的scoket单独放在一个线程,然后连接到来的多个socket放在其他几个线程,所以就有了两个创建Channel的地方,一个是在Acceptor构造中创建用于监听socket的通道,一个是新连接到来TcpConnection中创建的Channel。构造函数中传入了当前所属的事件循环和文件fd。
注册回调
acceptChannel_.setReadCallback(std::bind(&Acceptor::handleRead, this));channel_->setReadCallback(std::bind(&TcpConnection::handleRead, this, std::placeholders::_1));
channel_->setWriteCallback(std::bind(&TcpConnection::handleWrite, this));
channel_->setCloseCallback(std::bind(&TcpConnection::handleClose, this));
channel_->setErrorCallback(std::bind(&TcpConnection::handleError, this));
前面说了,两个地方创建了Channel,所以回调也设置也不同,Acceptor中Channel回调指向了Acceptor的handle函数,进而指向了TcpServer的newconnetion(),而TcpConnection中Channel则是回调到了TcpConnection中。
处理事件
void Channel::handleEvent(Timestamp receiveTime)
{std::shared_ptr<void> guard;if (tied_){guard = tie_.lock();if (guard){handleEventWithGuard(receiveTime);}}else{handleEventWithGuard(receiveTime);}
}void Channel::handleEventWithGuard(Timestamp receiveTime)
{LOGD(reventsToString().c_str());if ((revents_ & XPOLLHUP) && !(revents_ & XPOLLIN)){if (logHup_){LOGW("Channel::handle_event() XPOLLHUP");}if (closeCallback_) closeCallback_();}if (revents_ & XPOLLNVAL){LOGW("Channel::handle_event() XPOLLNVAL");}if (revents_ & (XPOLLERR | XPOLLNVAL)){if (errorCallback_) errorCallback_();}if (revents_ & (XPOLLIN | XPOLLPRI | XPOLLRDHUP)){//当是侦听socket时,readCallback_指向Acceptor::handleRead//当是客户端socket时,调用TcpConnection::handleRead if (readCallback_) readCallback_(receiveTime);}if (revents_ & XPOLLOUT){//如果是连接状态服的socket,则writeCallback_指向Connector::handleWrite()if (writeCallback_) writeCallback_();}//eventHandling_ = false;
}
handleEvent中tie实际上这是一个弱指针,指向向他的拥有者TcpConnection,为什么要这么做呢?假如Channel正在处理事件,TcpConnection连接关闭销毁了,程序可能会dump,要保证TcpConnection不被销毁,因此Channel中存了一个TcpConnection的弱指针,在处理事件的时候,lock将引用计数加1保证TcpConnection不被销毁。
handleEventWithGuard根据revents_不同的值调用不同的回调函数,revents_的值是在Poll(IO多路复用类)设置的,由Poll检测是什么事件,给revents_赋相应的值,处理不同的事件。