欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

muduo库分析——net篇(1)EventLoop

程序员文章站 2022-06-14 10:18:19
...

类图:

muduo库分析——net篇(1)EventLoop

可以看出大概的关系

Channel负责注册删除和响应的IO事件,具有IO当前状态,持有相关的回调函数

EventLoop具有事件循环能力,从Poller中不停的读取IO事件,反馈到Channel上,执行Channel的回调函数

Poller持有Channel的map结构,形式为<int fd,Channel*>,其派生类会新增相关文件描述符集合(用于从系统调用中读取相关IO事件)

muduo库分析——net篇(1)EventLoop


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通过基类指针调用派生类函数