Getting Started 09 Network Programming

EventLoop.h

eventfd 是 Linux 的一个系统调用,创建一个文件描述符用于事件通知,自 Linux 2.6.22 以后开始支持。
`#include <sys/eventfd.h>`
`int eventfd(unsigned int initval, int flags);`
eventfd() 创建一个 eventfd 对象,可以由用户空间应用程序实现事件等待/通知机制,或由内核通知用户空间应用程序事件。
该对象包含了由内核维护的无符号64位整数计数器 count 。使用参数 initval 初始化此计数器。
flags 可以是以下值的 OR 运算结果,用以改变 eventfd 的行为。

EFD_CLOEXEC (since Linux 2.6.27)
文件被设置成 O_CLOEXEC,创建子进程 (fork) 时不继承父进程的文件描述符。
EFD_NONBLOCK (since Linux 2.6.27)
文件被设置成 O_NONBLOCK,执行 read / write 操作时,不会阻塞。
EFD_SEMAPHORE (since Linux 2.6.30)
提供类似信号量语义的 read 操作,简单说就是计数值 count 递减 1。
在 Linux 2.6.26 版本之前,没有使用参数 flags,必须指定为 0。


对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。信号,为 Linux 提供了一种处理异步事件的方法。比如,终端用户输入了 ctrl+c 来中断程序,会通过信号机制停止一个程序。
信号的名字和编号:
1每个信号都有一个名字和编号,这些名字都以“SIG”开头,例如“SIGIO ”、“SIGCHLD”等等。
2信号的处理有三种方法,分别是:忽略、捕捉和默认动作


忽略信号,大多数信号可以使用这个方式来处理,但是有两种信号不能被忽略(分别是 SIGKILL和SIGSTOP)。因为他们向内核和超级用户提供了进程终止和停止的可靠方法,如果忽略了,那么这个进程就变成了没人能管理的的进程,显然是内核设计者不希望看到的场景

捕捉信号,需要告诉内核,用户希望如何处理某一种信号,说白了就是写一个信号处理函数,然后将这个函数告诉内核。当该信号产生时,由内核来调用用户自定义的函数,以此来实现某种信号的处理。

系统默认动作,对于每个信号来说,系统都对应由默认的处理动作,当发生了该信号,系统会自动执行。不过,对系统来说,大部分的处理方式都比较粗暴,就是直接杀死该进程。

__thread EventLoop* t_loopInThisThread = 0; //线程变量

const int kPollTimeMs = 10000;

int createEventfd()
{
  int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
  if (evtfd < 0)
  {
    LOG_SYSERR << "Failed in eventfd";
    abort();
  }
  return evtfd;
}

class IgnoreSigPipe 
{
 public:
  IgnoreSigPipe()
  {
    ::signal(SIGPIPE, SIG_IGN);   //忽略SIGPIPE
    // LOG_TRACE << "Ignore SIGPIPE";
  }
};

IgnoreSigPipe initObj;//创建了一个对象

class EventLoop {
public:
     typedef std::function<void()> Functor;  
private:
     typedef std::vector<Channel*> ChannelList;


     bool looping_; /* atomic */  

     std::atomic<bool> quit_;

     bool eventHandling_; /* atomic */

     bool callingPendingFunctors_; /* atomic */

     int64_t iteration_;

     const pid_t threadId_;

     Timestamp pollReturnTime_;

    std::unique_ptr<Poller> poller_;

    std::unique_ptr<TimerQueue> timerQueue_;

    int wakeupFd_;

    // unlike in TimerQueue, which is an internal class,
    // we don't expose Channel to client.
    std::unique_ptr<Channel> wakeupChannel_;

    boost::any context_;

    ChannelList activeChannels_;

    Channel* currentActiveChannel_;  //当前活跃频道

    mutable MutexLock mutex_;

    std::vector<Functor> pendingFunctors_ GUARDED_BY(mutex_);
public:


    EventLoop()
      : looping_(false),
    quit_(false),
    eventHandling_(false),
    callingPendingFunctors_(false),
    iteration_(0),
    threadId_(CurrentThread::tid()),  //设置线程id
    poller_(Poller::newDefaultPoller(this)), //创建一个默认轮训器
    timerQueue_(new TimerQueue(this)), //创建一个定时器队列
    wakeupFd_(createEventfd()),  //单纯理解为创建了一个事件描述符
    wakeupChannel_(new Channel(this, wakeupFd_)), //将频道和文件描述符绑定
    currentActiveChannel_(NULL)   
    {
          LOG_DEBUG << "EventLoop created " << this << " in thread " << threadId_;
          if (t_loopInThisThread)            //如果这个线程已经有EventLoop对象
          {
            LOG_FATAL << "Another EventLoop " << t_loopInThisThread
                      << " exists in this thread " << threadId_;
           }
          else
          {
            t_loopInThisThread = this;
          }
          wakeupChannel_->setReadCallback(          
                  std::bind(&EventLoop::handleRead, this));          //绑定处理有读事件的回调函数
          // we are always reading the wakeupfd
          wakeupChannel_->enableReading();  //运去读
    }

   void EventLoop::handleRead()
    {
      uint64_t one = 1;
      ssize_t n = sockets::read(wakeupFd_, &one, sizeof one);   //读取wakeupFd事件
      if (n != sizeof one)
      {
            LOG_ERROR << "EventLoop::handleRead() reads " << n << " bytes instead of 8";
      }
    }
   ~EventLoop() {
      wakeupChannel_->disableAll();   
      wakeupChannel_->remove();
      ::close(wakeupFd_);
      t_loopInThisThread = NULL;
   }
   void loop() {
       assert(!looping_);
       assertInLoopThread();
       looping_ = true;
       quit_ = false;
       while (!quit_)
      {
            activeChannels_.clear();
            pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);  //让轮训器去询问有没有事件等就绪
            ++iteration_;  //迭代数目+1
            if (Logger::logLevel() <= Logger::TRACE)
            {
              printActiveChannels();
            }
            // TODO sort channel by priority
            eventHandling_ = true;
            for (Channel* channel : activeChannels_)      //处理每一个活跃频道的事件
            {
              currentActiveChannel_ = channel;  //当前活跃频道
              currentActiveChannel_->handleEvent(pollReturnTime_);  调用回调函数
            }
            currentActiveChannel_ = NULL;
            eventHandling_ = false;
            doPendingFunctors();
      }
      looping_ = false;
   }
   void doPendingFunctors() {
       std::vector<Functor> functors; 
      callingPendingFunctors_ = true; 
      {
          MutexLockGuard lock(mutex_);
          functors.swap(pendingFunctors_);
      }
      for (const Functor& functor : functors)  //调用栈上对象,尽量减少锁的粒度
      {
            functor();
      }
      callingPendingFunctors_ = false;
   }
      void EventLoop::printActiveChannels() const 打印当前活跃频道
    {
      for (const Channel* channel : activeChannels_)
      {
        LOG_TRACE << "{" << channel->reventsToString() << "} ";
      }
   }
   
   void quit() {
      quit_ = true;
     if (!isInLoopThread())
    {
        wakeup();
    }
   }
   
    void wakeup() {
      uint64_t one = 1;
      ssize_t n = sockets::write(wakeupFd_, &one, sizeof one);
      if (n != sizeof one)
      {
        LOG_ERROR << "EventLoop::wakeup() writes " << n << " bytes instead of 8";
      }
   } 
  
   void EventLoop::runInLoop(Functor cb)
    {
      if (isInLoopThread())
     {
        cb();
      }
      else
      {
           queueInLoop(std::move(cb));
      }
    }
 
    void EventLoop::queueInLoop(Functor cb)
    {
          {
          MutexLockGuard lock(mutex_);
          pendingFunctors_.push_back(std::move(cb));
          }    

          if (!isInLoopThread() || callingPendingFunctors_)
          {
                wakeup();
          }
    }

    size_t EventLoop::queueSize() const
   {
      MutexLockGuard lock(mutex_);
      return pendingFunctors_.size();
    }

    TimerId EventLoop::runAt(Timestamp time, TimerCallback cb)
{
  return timerQueue_->addTimer(std::move(cb), time, 0.0);
}

TimerId EventLoop::runAfter(double delay, TimerCallback cb)
{
  Timestamp time(addTime(Timestamp::now(), delay));
  return runAt(time, std::move(cb));
}

TimerId EventLoop::runEvery(double interval, TimerCallback cb)
{
  Timestamp time(addTime(Timestamp::now(), interval));
  return timerQueue_->addTimer(std::move(cb), time, interval);
}

void EventLoop::cancel(TimerId timerId)
{
  return timerQueue_->cancel(timerId);
}

void EventLoop::updateChannel(Channel* channel)
{
  assert(channel->ownerLoop() == this);
  assertInLoopThread();
  poller_->updateChannel(channel);
}

void EventLoop::removeChannel(Channel* channel)
{
  assert(channel->ownerLoop() == this);
  assertInLoopThread();
  if (eventHandling_)
  {
    assert(currentActiveChannel_ == channel ||
        std::find(activeChannels_.begin(), activeChannels_.end(), channel) == activeChannels_.end());
  }
  poller_->removeChannel(channel);
}

bool EventLoop::hasChannel(Channel* channel)
{
  assert(channel->ownerLoop() == this);
  assertInLoopThread();
  return poller_->hasChannel(channel);
}


}

Guess you like

Origin www.cnblogs.com/aiqingyi/p/11323168.html