网络编程入门09

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);
}
}

EventLoopThread.h

class EventLoopThread {
public:
    typedef std::function<void(EventLoop*)> ThreadInitCallback;   //一个带有EventLoop指针的可调用对象,定义为ThreadInilCallback
private:
    EventLoop* loop_;
    bool exiting_;
    Thread thread_;
    Mutex mutex_;
    Condition cond_;
    ThreadInitCallback callback_;
public:

    EventLoopThread(const ThreadInitCallback&cb = ThreadInitCallback(),  const string& name = string())  
  : loop_(NULL),
    exiting_(false),
    thread_(std::bind(&EventLoopThread::threadFunc, this), name),  //注意绑定了threadFunc
    mutex_(),
    cond_(mutex_),
    callback_(cb)
    {}

    ~EventLoopThread() 
{
  exiting_ = true;
  if (loop_ != NULL) // not 100% race-free, eg. threadFunc could be running callback_.
  {
    // still a tiny chance to call destructed object, if threadFunc exits just now.
    // but when EventLoopThread destructs, usually programming is exiting anyway.
    loop_->quit();
    thread_.join();
  }
}

    EventLoop* startLoop()
{
  assert(!thread_.started());
  thread_.start();

  EventLoop* loop = NULL;
  {
    MutexLockGuard lock(mutex_);
    while (loop_ == NULL)
    {
      cond_.wait();
    }
    loop = loop_;
  }
  return loop;
}

private:
    void threadFunc()
{
  EventLoop loop;

  if (callback_)
  {
    callback_(&loop);
  }

  {
    MutexLockGuard lock(mutex_);
    loop_ = &loop;
    cond_.notify();
  }

  loop.loop();
  //assert(exiting_);
  MutexLockGuard lock(mutex_);
  loop_ = NULL;
}

}

EventLoopThreadPool.h

//这个线程池给人感觉。。缺少了一点点东西。。后边看看能不能理解把,本身提供的接口很简单。
class EventLoopThreadPool {
public:
    typedef std::function<void(EventLoop*)> ThreadInitCallback;
private:
    EventLoop* baseLoop_;
    string name_;
    bool started_;
    int numThreads_;
    int next_;
    std::vector<std::unique_ptr<EventLoopThread> > threads_;
    std::vector<EventLoop*> loops_;

public:

    EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg) 
      : baseLoop_(baseLoop),
    name_(nameArg),
    started_(false),
    numThreads_(0),
    next_(0)
    {
    }

    ~EventLoopThreadPool()
    {
      // Don't delete loop, it's stack variable
    }
    
    void setThreadNum(int numThreads) { numThreads_ = numThreads; }
    
    void start(const ThreadInitCallback& cb)
    {
      assert(!started_);
      baseLoop_->assertInLoopThread();

      started_ = true;

      for (int i = 0; i < numThreads_; ++i)
      {
        char buf[name_.size() + 32];
        snprintf(buf, sizeof buf, "%s%d", name_.c_str(), i);
        EventLoopThread* t = new EventLoopThread(cb, buf);
        threads_.push_back(std::unique_ptr<EventLoopThread>(t));
        loops_.push_back(t->startLoop());
      }
      if (numThreads_ == 0 && cb)
      {
        cb(baseLoop_);
      }
    }

  bool started() const
  { return started_; }

  const string& name() const
  { return name_; }

    EventLoop* getNextLoop() 
    {
      baseLoop_->assertInLoopThread();
      assert(started_);
      EventLoop* loop = baseLoop_;

     if (!loops_.empty())
      {
        // round-robin
        loop = loops_[next_];
        ++next_;
        if (implicit_cast<size_t>(next_) >= loops_.size())
        {
          next_ = 0;
        }
      }
      return loop;
    }

    EventLoop* getLoopForHash(size_t hashCode)
{
  baseLoop_->assertInLoopThread();
  EventLoop* loop = baseLoop_;

  if (!loops_.empty())
  {
    loop = loops_[hashCode % loops_.size()];
  }
  return loop;
}

std::vector<EventLoop*> EventLoopThreadPool::getAllLoops()
{
  baseLoop_->assertInLoopThread();
  assert(started_);
  if (loops_.empty())
  {
    return std::vector<EventLoop*>(1, baseLoop_);
  }
  else
  {
    return loops_;
  }
}

}

转载于:https://www.cnblogs.com/aiqingyi/p/11323168.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值