Channel是IO时间的分发器,负责注册和响应IO事件。每个Channel对象自始至终只负责一个文件描述符的IO事件分发,但它并不拥有这个fd,也不会在析构的时候关闭这个fd。
const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = POLLIN | POLLPRI;
const int Channel::kWriteEvent = POLLOUT;
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()
{
assert(!eventHandling_);
assert(!addedToLoop_);
if (loop_->isInLoopThread())
{
assert(!loop_->hasChannel(this));
}
}
void Channel::tie(const std::shared_ptr<void>& obj)
{
tie_ = obj;
tied_ = true;
}
Channel::kReadEvent和Channel::kWriteEvent也就是muduo库所关心的读写事件,POLLOUT---普通数据可写;POLLIN---可读取非高优先级的数据;POLLPRI---可读取高优先级数据。event_是它关心的IO事件,revents_是目前活动的事件。
Channel中的tie_实现的功能貌似只在TcpConnection中使用。对于TcpConnection,如果在Channel中调用Channel::handleEvent()时,执行closeCallback_,有可能引发TcpConnection析构,继而把当前Channel对象也析构了,引起程序崩溃。所以在执行Channel::handleEvent()时,获取一份TcpConnection的shared_ptr,防止TcpConnection析构。
void Channel::handleEvent(Timestamp receiveTime)
{
std::shared_ptr<void> guard;
if (tied_)
{
guard = tie_.lock();
if (guard)
{
handleEventWithGuard(receiveTime);
}
}
else
{
handleEventWithGuard(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::handleEventWithGuard()中使用,关于Channel::handleEventWithGuard()涉及的各种事件类型参考https://blog.csdn.net/qu1993/article/details/109517303 。这里不再说Channel::handleEventWithGuard()函数。因为Channel的事件处理功能,也就是Channel::handleEvent()需要由EventLoop来调用,所以需要将Channel添加到EventLoop,当关心的事件类型修改后,也要随时更新到EventLoop。当然,实际上这些操作都是EventLoop通过Poller实现的。
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; }
void Channel::update()
{
addedToLoop_ = true;
loop_->updateChannel(this);
}
通过Channel的index_标志来确定更新的方式是添加还是修改。
void Channel::remove()
{
assert(isNoneEvent());
addedToLoop_ = false;
loop_->removeChannel(this);
}
将添加到EventLoop的Channel移除。