Muduo::eventloopthread, Eventloopthreadpool analysis

Source: Internet
Author: User
Tags assert

Eventloopthread Eventloopthreadpool

The concurrency model for Muduo is one loop per thread+ ThreadPool. For ease of use, the Muduo encapsulates the EventLoop and thread as Eventloopthread, in order to facilitate the use of the thread pool and eventloopthread encapsulation as eventloopthreadpool. Eventloopthread

Any thread, as long as EventLoop is created and run, is an IO thread.
The Eventloopthread class is a encapsulated IO thread.
The Eventloopthread workflow is:
1. Create the Eventloopthread object in the main thread (this is called).
2. The main thread calls Eventloopthread.start (), starts the thread in the Eventloopthread (called the IO thread), which is the main thread to wait for the IO thread to create the completed EventLoop object.
3. The IO thread calls ThreadFunc to create the EventLoop object. Notifies the main thread that the master thread has been created.
4. The main thread returns the created EventLoop object.

EventLoopThread.h

Class eventloopthread:boost::noncopyable
{public
 :
  typedef boost::function<void (eventloop*) > Threadinitcallback;

  Eventloopthread (const threadinitcallback& CB = Threadinitcallback (),
                  const string& name = string ());
  ~eventloopthread ();
  eventloop* Startloop ();//start this thread, return eventloop

 private:
  void ThreadFunc () in this thread;

  eventloop* loop_;//This thread holds the EventLoop object pointer
  bool exiting_;//has exited thread
  thread_;//this thread mutexlock
  mutex_ ;
  Condition Cond_;
  Threadinitcallback callback_;//callback function
};

eventloopthread.cc

Eventloopthread::eventloopthread (const threadinitcallback& CB, const string& Name ): Loop_ (NULL), Exiting_ (false), Thread_ (Boost::bind (&eventloopthread::threadfunc, this), name),//create thread in callback letter Number created EventLoop mutex_ (), Cond_ (mutex_), Callback_ (CB) {} eventloopthread::~eventloopthread () {exiting_ = tr
  Ue 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 was exiting anyway. Loop_->quit ();//exit Loop loop Thread_.join ();//wait for thread to exit}} eventloop* Eventloopthread::startloop ()//Another thread calling this function {a
  Ssert (!thread_.started ());
    Thread_.start ();//When the front thread starts, call ThreadFunc () {Mutexlockguard lock (mutex_);
while (loop_ = = NULL) {cond_.wait ();//wait to create a good current IO thread}} return loop_; } void Eventloopthread::threadfunc () {EventlOOP loop;//Create EventLoop objects.
  Note that on the stack if (callback_) {callback_ (&loop);
    } {Mutexlockguard lock (mutex_);
    Loop_ = &loop; Cond_.notify ();//Notify Startloop} loop.loop ();//will loop here until Eventloopthread is destructor.
  Thereafter no longer use LOOP_ to access EventLoop//assert (exiting_);
Loop_ = NULL; }
Eventloopthreadpool

Muduo thought when Eventloop+thread pool, in order to be more convenient to use, will eventloopthread do the encapsulation. Main reactor can create sub reactor, and some tasks are distributed to sub reactor.

The idea of Eventloopthreadpool is relatively simple, creating eventloopthreadpool with a main reactor. Binding EventLoop and thread in Eventloopthreadpool, you can return EventLoop objects to use the thread in Eventloopthreadpool.

EventLoopThreadPool.h

Class EventLoop;

Class eventloopthread:boost::noncopyable
{public
 :
  typedef boost::function<void (eventloop*) > Threadinitcallback;

  Eventloopthread (const threadinitcallback& CB = Threadinitcallback (),
                  const string& name = string ());
  ~eventloopthread ();
  eventloop* Startloop ();//start this thread, return eventloop

 private:
  void ThreadFunc () in this thread;

  eventloop* loop_;//This thread holds the EventLoop object pointer
  bool exiting_;//has exited thread
  thread_;//this thread mutexlock
  mutex_ ;
  Condition Cond_;
  Threadinitcallback callback_;//callback function
};

eventloopthreadpool.cc

Eventloopthreadpool::eventloopthreadpool (eventloop* baseloop, const string& namearg): BaseLoop_ (baseLoop), name _ (Namearg), Started_ (false), Numthreads_ (0), Next_ (0) {} eventloopthreadpool::~eventloopthreadpool () {// Don ' t delete loop, it's stack variable} void Eventloopthreadpool::start (const threadinitcallback& CB) {ASSERT (!st
  ARTED_);

  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 (t);
  Loops_.push_back (T->startloop ());
  } if (Numthreads_ = = 0 && cb) {CB (BASELOOP_);
  }} eventloop* Eventloopthreadpool::getnextloop () {baseloop_->assertinloopthread ();
  ASSERT (Started_); eventloop* loop = Baseloop_;//loops_ is empty, returns Baseloop if (!loops_.empty ())//Cyclic allocation {//Round-robin loop = loops_[ Next_];
    ++next_;
    if (implicit_cast<size_t> (next_) >= loops_.size ()) {next_ = 0;
}} return loop;
  } eventloop* Eventloopthreadpool::getloopforhash (size_t hashcode) {baseloop_->assertinloopthread ();

  eventloop* loop = Baseloop_;
if (!loops_.empty ()) {loop = loops_[hashcode% loops_.size ()];//according to hashcode allocation} return loop;
  } std::vector<eventloop*> Eventloopthreadpool::getallloops () {baseloop_->assertinloopthread ();
  ASSERT (Started_);
  if (Loops_.empty ()) {return std::vector<eventloop*> (1, BASELOOP_);
  } else {return loops_; }
}

You can write a simple test program, create a eventloopthreadpool, print the ID and name of the thread.

#include <muduo/net/EventLoop.h>
#include <muduo/net/EventLoopThread.h>
#include <muduo/ net/eventloopthreadpool.h>

#include <stdio.h>

using namespace Muduo;
using namespace muduo::net;

void Runinthread ()
{
    printf ("Runinthread (): name =%s, Tid =%d\n",
           currentthread::name (), CurrentThread:: Tid ());
}

int main ()
{
    printf ("Main (): PID =%d, Tid =%d\n",
           getpid (), Currentthread::tid ());

    Runinthread ();
    EventLoop Loop;
    Eventloopthreadpool Loopthreadpool (&loop, "sub Reactor");
    Loopthreadpool.setthreadnum (5);
    Loopthreadpool.start ();
    for (int i=0; i<10; ++i)
    {
        eventloop* loopfrompool=loopthreadpool.getnextloop ();
        Loopfrompool->runinloop (Runinthread);
    }
    Sleep (3);
    printf ("Exit main () \ n");
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.