EventLoopThread (30)

来源:互联网 发布:福州seo基础培训 编辑:程序博客网 时间:2024/06/02 10:59
  1. 任何一个线程,只要创建并运行了EventLoop,都称之为IO线程

  2. IO线程不一定是主线程

  3. muduo并发模型one loop per thread + threadpool

  4. 为了方便今后使用,定义了EventLoopThread类,该类封装了IO线程EventLoopThread创建了一个线程

  5. 在线程函数中创建了一个EvenLoop对象并调用EventLoop::loop






EventLoopThread头文件

eventloopthread.h

// Copyright 2010, Shuo Chen.  All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is a public header file, it must only include public header files.#ifndef MUDUO_NET_EVENTLOOPTHREAD_H#define MUDUO_NET_EVENTLOOPTHREAD_H#include <muduo/base/Condition.h>#include <muduo/base/Mutex.h>#include <muduo/base/Thread.h>#include <boost/noncopyable.hpp>namespace muduo{namespace net{class EventLoop;class EventLoopThread : boost::noncopyable{ public:  typedef boost::function<void(EventLoop*)> ThreadInitCallback;  EventLoopThread(const ThreadInitCallback& cb =ThreadInitCallback());   ~EventLoopThread();  EventLoop* startLoop();   // 启动线程,该线程就成为了IO线程 private:  void threadFunc();        // 线程函数 ,这个线程函数启动起来之后,会创建一个eventloop对象,loop_指针会指向这个对象  EventLoop* loop_;         // loop_指针指向一个EventLoop对象,一个IO线程有且只有一个eventloop对象  bool exiting_;  Thread thread_;       //线程对象  MutexLock mutex_;  Condition cond_;  ThreadInitCallback callback_;     // 回调函数在EventLoop::loop IO线程的事件循环之前被调用};}}#endif  // MUDUO_NET_EVENTLOOPTHREAD_H


EventLoopThread源文件

eventloopthread.cc


// Copyright 2010, Shuo Chen.  All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)#include <muduo/net/EventLoopThread.h>#include <muduo/net/EventLoop.h>#include <boost/bind.hpp>using namespace muduo;using namespace muduo::net;// typedef boost::function<void(EventLoop*)> ThreadInitCallback;EventLoopThread::EventLoopThread(const ThreadInitCallback& cb)  : loop_(NULL),    exiting_(false),    thread_(boost::bind(&EventLoopThread::threadFunc, this)),    mutex_(),    cond_(mutex_),    callback_(cb)  //cb 默认为空{}EventLoopThread::~EventLoopThread(){  exiting_ = true;  loop_->quit();     // 退出IO线程,让IO线程的loop循环退出,从而退出了IO线程  thread_.join();}/*启动线程,也就是启动loop函数EventLoopThread::threadFunc这个函数*/EventLoop* EventLoopThread::startLoop(){  assert(!thread_.started());  /*线程启动时会调用*/  thread_.start();  {    MutexLockGuard lock(mutex_);    /*eventloop对象创建完成*/    while (loop_ == NULL)    {      cond_.wait();    }  }  return loop_;}/*loop 的初始化函数*/void EventLoopThread::threadFunc(){  EventLoop loop;  /*创建eventloop对象*/  if (callback_)  {    callback_(&loop);  }  {    MutexLockGuard lock(mutex_);    // loop_指针指向了一个栈上的对象,threadFunc函数退出之后,这个指针就失效了    // threadFunc函数退出,就意味着线程退出了,EventLoopThread对象也就没有存在的价值了。    // 因而不会有什么大的问题    loop_ = &loop;    cond_.notify();  }  /*启动loop()函数*/  loop.loop();  //assert(exiting_);}



测试程序

#include <muduo/net/EventLoop.h>#include <muduo/net/EventLoopThread.h>#include <stdio.h>using namespace muduo;using namespace muduo::net;void runInThread(){  printf("runInThread(): pid = %d, tid = %d\n",         getpid(), CurrentThread::tid());}int main(){  printf("main(): pid = %d, tid = %d\n",         getpid(), CurrentThread::tid());  EventLoopThread loopThread;  EventLoop* loop = loopThread.startLoop();  // 异步调用runInThread,即将runInThread添加到loop对象所在IO线程,让该IO线程执行  loop->runInLoop(runInThread);  sleep(1);  // runAfter内部也调用了runInLoop,所以这里也是异步调用  loop->runAfter(2, runInThread);  sleep(3);  loop->quit();  printf("exit main().\n");}/*TimerId TimerQueue::addTimer(const TimerCallback& cb,                             Timestamp when,                             double interval){  Timer* timer = new Timer(cb, when, interval);  loop_->runInLoop(      boost::bind(&TimerQueue::addTimerInLoop, this, timer));  //addTimerInLoop(timer); 不能用这个,如果直接调用,那么addTimerInLoop断言失败  return TimerId(timer, timer->sequence());}void TimerQueue::addTimerInLoop(Timer* timer){  loop_->assertInLoopThread();  // 插入一个定时器,有可能会使得最早到期的定时器发生改变  bool earliestChanged = insert(timer);  if (earliestChanged)  {    // 重置定时器的超时时刻(timerfd_settime)    resetTimerfd(timerfd_, timer->expiration());  }}bool TimerQueue::insert(Timer* timer){  loop_->assertInLoopThread();  assert(timers_.size() == activeTimers_.size());  // 最早到期时间是否改变  bool earliestChanged = false;  Timestamp when = timer->expiration();  TimerList::iterator it = timers_.begin();  // 如果timers_为空或者when小于timers_中的最早到期时间  if (it == timers_.end() || when < it->first)  {    earliestChanged = true;  }  {    // 插入到timers_中    std::pair<TimerList::iterator, bool> result      = timers_.insert(Entry(when, timer));    assert(result.second); (void)result;  }  {    // 插入到activeTimers_中    std::pair<ActiveTimerSet::iterator, bool> result      = activeTimers_.insert(ActiveTimer(timer, timer->sequence()));    assert(result.second); (void)result;  }  assert(timers_.size() == activeTimers_.size());  return earliestChanged;}*/


程序输出

ubuntu@ubuntu-virtual-machine:~/pro/30$ ./build/debug/bin/reactor_test06 main(): pid = 29731, tid = 2973120131022 03:03:50.315042Z 29732 TRACE updateChannel fd = 4 events = 3 - EPollPoller.cc:10420131022 03:03:50.315588Z 29732 TRACE EventLoop EventLoop created 0xB786BF94 in thread 29732 - EventLoop.cc:6220131022 03:03:50.315643Z 29732 TRACE updateChannel fd = 5 events = 3 - EPollPoller.cc:10420131022 03:03:50.315708Z 29732 TRACE loop EventLoop 0xB786BF94 start looping - EventLoop.cc:9420131022 03:03:50.315976Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:50.316472Z 29732 TRACE printActiveChannels {5: IN }  - EventLoop.cc:257runInThread(): pid = 29731, tid = 2973220131022 03:03:51.316968Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:51.317092Z 29732 TRACE printActiveChannels {5: IN }  - EventLoop.cc:25720131022 03:03:53.317414Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:53.317539Z 29732 TRACE printActiveChannels {4: IN }  - EventLoop.cc:25720131022 03:03:53.317639Z 29732 TRACE readTimerfd TimerQueue::handleRead() 1 at 1382411033.317576 - TimerQueue.cc:62runInThread(): pid = 29731, tid = 29732exit main().20131022 03:03:54.317901Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:54.317966Z 29732 TRACE printActiveChannels {5: IN }  - EventLoop.cc:25720131022 03:03:54.317990Z 29732 TRACE loop EventLoop 0xB786BF94 stop looping - EventLoop.cc:119ubuntu@ubuntu-virtual-machine:~/pro/30$