muduo库分析——net篇(1)EventLoop
程序员文章站
2022-06-14 10:18:19
...
类图:
可以看出大概的关系
Channel负责注册删除和响应的IO事件,具有IO当前状态,持有相关的回调函数
EventLoop具有事件循环能力,从Poller中不停的读取IO事件,反馈到Channel上,执行Channel的回调函数
Poller持有Channel的map结构,形式为<int fd,Channel*>,其派生类会新增相关文件描述符集合(用于从系统调用中读取相关IO事件)
EventLoop.cpp
wakeupChannel_->setReadCallback(
boost::bind(&EventLoop::handleRead, this));
// we are always reading the wakeupfd
wakeupChannel_->enableReading();
在构造函数中进行IO事件注册,wakeupChannel用于线程唤醒,当其他线程要关闭当前线程Loop时,调用quit函数,使用wakeupChannel发送数据,阻塞在poller_->poll(kPollTimeMs, &activeChannels_);时候就会获得返回并执行下去,退出while循环
while (!quit_)
{
activeChannels_.clear(); //清理活跃中的IO通道
pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_); //等待Poller将活跃的IO通道传送过来
++iteration_;
if (Logger::logLevel() <= Logger::TRACE)
{
printActiveChannels(); //输出通道
}
// TODO sort channel by priority
eventHandling_ = true; //处理事件状态
for (ChannelList::iterator it = activeChannels_.begin(); //遍历每个IO通道处理相关事件
it != activeChannels_.end(); ++it)
{
currentActiveChannel_ = *it;
currentActiveChannel_->handleEvent(pollReturnTime_);
}
currentActiveChannel_ = NULL;
eventHandling_ = false;
doPendingFunctors();
}
void EventLoop::updateChannel(Channel* channel) //更新Poller中Channel对应文件描述符状态
{
assert(channel->ownerLoop() == this);
assertInLoopThread();
poller_->updateChannel(channel);
}
Channel.h和Channel.cpp
EventLoop* loop_; //持有事件循环指针
const int fd_; //持有文件描述符ID
int events_; //感兴趣的事件
int revents_; // it's the received event types of epoll or poll 获得的事件反馈
int index_; // used by Poller. EPoller中代表当前IO活动状态,Poller中代表当前IO所在Poller文件描述符数组的下标位置
bool logHup_;
boost::weak_ptr<void> tie_;
bool tied_;
bool eventHandling_;
bool addedToLoop_;
ReadEventCallback readCallback_; //事件回调函数
EventCallback writeCallback_;
EventCallback closeCallback_;
EventCallback errorCallback_;
void Channel::handleEvent(Timestamp receiveTime)
{
boost::shared_ptr<void> guard;
if (tied_)
{
guard = tie_.lock();
if (guard)
{
handleEventWithGuard(receiveTime);
}
}
else
{
handleEventWithGuard(receiveTime);
}
}
void Channel::handleEventWithGuard(Timestamp receiveTime)
上面是Channel调用函数的过程,根据revents的状态码执行响应的动作Poller.h和Poller.cpp
protected:
typedef std::map<int, Channel*> ChannelMap;
ChannelMap channels_; // fd,Channel 集合
virtual Timestamp poll(int timeoutMs, ChannelList* activeChannels) = 0;
/// Changes the interested I/O events.
/// Must be called in the loop thread.
virtual void updateChannel(Channel* channel) = 0;
/// Remove the channel, when it destructs.
/// Must be called in the loop thread.
virtual void removeChannel(Channel* channel) = 0;
virtual bool hasChannel(Channel* channel) const;
static Poller* newDefaultPoller(EventLoop* loop);
几个派生类需要实现的函数,EventLoop通过基类指针调用派生类函数