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 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 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_赋相应的值,处理不同的事件。