Muduo library analysis - net articles (1) EventLoop

Class Diagram:


It can be seen that the approximate relationship

Channel is responsible for registering deleted and responding IO events, has the current state of IO, and holds related callback functions

EventLoop has the event loop capability. It continuously reads IO events from the Poller, feeds them back to the Channel, and executes the callback function of the Channel.

Poller holds the map structure of Channel in the form of <int fd, Channel*>, and its derived class will add a set of related file descriptors (used to read related IO events from system calls)



EventLoop.cpp

  wakeupChannel_->setReadCallback(
      boost::bind(&EventLoop::handleRead, this));
  // we are always reading the wakeupfd
  wakeupChannel_->enableReading();

Perform IO event registration in the constructor, wakeupChannel is used for thread wakeup, when other threads want to close the current thread Loop, call the quit function, use wakeupChannel to send data, and block in poller_->poll(kPollTimeMs, &activeChannels_); Go back and continue, exit the while loop

while (!quit_)
  {
    activeChannels_.clear(); //Clear active IO channels
    pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_); //Wait for Poller to send active IO channels
    ++iteration_;
    if (Logger::logLevel() <= Logger::TRACE)
    {
      printActiveChannels(); //Output channels
    }
    // TODO sort channel by priority
    eventHandling_ = true; //Handle event status
    for (ChannelList::iterator it = activeChannels_.begin(); // Traverse each IO channel to process related events
        it != activeChannels_.end(); ++it)
    {
      currentActiveChannel_ = *it;
      currentActiveChannel_->handleEvent(pollReturnTime_);
    }
    currentActiveChannel_ = NULL;
    eventHandling_ = false;
    doPendingFunctors();
  }
void EventLoop::updateChannel(Channel* channel) //Update the status of the file descriptor corresponding to the Channel in the Poller
{
  assert(channel->ownerLoop() == this);
  assertInLoopThread();
  poller_->updateChannel(channel);
}

Channel.h和Channel.cpp

  EventLoop* loop_; //Holds the event loop pointer
  const int fd_; //holds the file descriptor ID
  int events_; //Events of interest
  int revents_; // it's the received event types of epoll or poll
  int index_; // used by Poller. EPoller represents the current IO activity status, and Poller represents the subscript position of the Poller file descriptor array where the current IO is located
  bool       logHup_;

  boost::weak_ptr<void> tie_;	
  bool tied_;
  bool eventHandling_;
  bool addedToLoop_;
  ReadEventCallback readCallback_; //Event callback function
  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)
The above is the process of calling the function of Channel, and the action of the response is executed according to the status code of revents

Poller.h and 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);
Several functions that derived classes need to implement, EventLoop calls derived class functions through the base class pointer



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325859971&siteId=291194637