Muduo 多线程模型对比 – KingsLanding

  制作节目8:reactor + thread pool ,有一根线充任起反应的人。 承认衔接散布事情,将要处置的事情分合理的事物线索 池中线索,按线索 pool 使筋疲力尽事情处置。旋转编码见:examples/sudoku/server_threadpool.cc

class SudokuServer

{

 public :

  SudokuServer(EventLoop* loop, const输出地址 listenAddr, int numThreads)

    : loop_(loop),

      server_(loop, listenAddr, “SudokuServer”),

      numThreads_(numThreads),

      StimeTime:(工夫戳:现时)

  {

    (

        boost::bind(&SudokuServer::onConnection, this, _1));

    (

        boost::bind(&SudokuServer::onMessage, this, _1, _2, _3));

  }

  void start()

  {

    LOG_INFO << “starting “ << numThreads_ << ” threads.”;

    (numThreads_); // 留意从此,threadPool 典型是: ThreadPool,外景开端了 外面

    ();

  }

 private :

  void onConnection(const TcpConnectionPtr& 康恩)

  {

    LOG_TRACE << conn->peerAddress().toIpPort() << ” -> “

        << conn->localAddress().toIpPort() << ” is “

        << (conn->connected() ? “UP” : “DOWN”);

  }

  void 在音讯中const TcpConnectionPtr& conn, Buffer* buf, 工夫戳

  {

        if (!processRequest(conn, 请) // 封装计算苦差事停止方式

        {

          conn->send( “Bad Request!\r\n”);

          conn->shutdown();

          break;

        }

      }

    }

  }

  bool processRequest(const TcpConnectionPtr& conn, const string& 请)

  {

    if (() == implicit_cast(kCells))

    {

      (Booo:):绑定(和处理), conn, puzzle, 身份证)// 将计算苦差事转变到 threadPool 线索

    }

    else

    {

      goodRequest = false;

    }

    return goodRequest;

  }

  static void solve(const TcpConnectionPtr& conn,

                    const string& puzzle,

                    const string& 身份证)

  {

    LOG_DEBUG << conn->name();

    string result = solveSudoku(puzzle); // solveSudou 这是独一无二地的 function, 它是可重入的的。 

    if (())

    {

      conn->send(result+ “\r\n”);

    }

    else

    {

      conn->send(id+ “:”+result+ “\r\n”);

    }

  }

  EventLoop* loop_;

  TcpServer server_;

  ThreadPool threadPool_; // 留意典型,制作节目8, reactor + threadpool

  int numThreads_;

  Timestamp startTime_;

};

void线索池:开端 int numThreads)  // 使成为 thread pool,假设的线索 此处调整未暂时辨析

{

  assert(());

  running_ = true;

  (numThreads);

  for (int i = 0; i < numThreads; ++i)

  {

    charID〔32〕

    snprintf(id, sizeof id, “%d”, i);

    ( new muduo::Thread(

          boost::bind(&ThreadPool::runInThread, this), name_+身份证)

    线索[i]开端

  }

}

制作节目9:main-reactor + subreactors, one loop per thread, 主起反应的人有任一主线 特意表现 accept 衔接,停止线索符合读写用锉锉描画符(套接字)。

class SudokuServer

{

 public :

  SudokuServer(EventLoop* loop, const 输出地址 listenAddr, int numThreads)

    : loop_(loop),

      server_(loop, listenAddr, “SudokuServer”),

      numThreads_(numThreads),

      StimeTime:(工夫戳:现时)

  {

    (

        boost::bind(&SudokuServer::onConnection, this, _1));

    (

        boost::bind(&SudokuServer::onMessage, this, _1, _2, _3));

    (numThreads); // 设置 事情环线索中线索的数目

  }

  void start()

  {

    LOG_INFO << “starting “ << numThreads_ << ” threads.”;

    ();

  }

 private :

  void onConnection(const TcpConnectionPtr& 康恩)

  {

    LOG_TRACE << conn->peerAddress().toIpPort() << ” -> “

        << conn->localAddress().toIpPort() << ” is “

        << (conn->connected() ? “UP” : “DOWN”);

  }

  void 在音讯中const TcpConnectionPtr& conn, Buffer* buf, 工夫戳

  {

        if (!processRequest(conn, 请) //预备计算

        {

          conn->send( “Bad Request!\r\n”);

          conn->shutdown();

          break;

        }

    }

  }

  bool processRequest(const TcpConnectionPtr& conn, const string& 请)

  {

    if (() == implicit_cast(kCells))

    {

      LOG_DEBUG << conn->name();

      string result = solveSudoku(puzzle); // 计算在流行的线索中使筋疲力尽。

      if (())

      {

        conn->send(result+ “\r\n”);

      }

  }

  // 留意从此没典型为ThreadPool的 threadPool_围攻,全体数量类应用Muduo默许线索用模子做的EventLoopThreadPool,TcpServer 凑合了EventLoopThreadPool

  EventLoop* loop_;

  TcpServer server_;

  int numThreads_;

  Timestamp startTime_;

};

void TcpServer::setThreadNum( int numThreads)

{

  断言(0) <= numThreads);

  threadPool_->setThreadNum(numThreads); // 设置了 EventLoopThreadPool 国内的线索的数目,为他日的TracePoLoLy->启动侍者

}

void TcpServer::start()

{

  if (!started_)

  {

    started_ = true;

    threadPool_->start(threadInitCallback_); // TcpServer 说话中肯 threadPool 典型是 EventLoopThreadPool

  }

  if (!acceptor_->listenning())

  {

    loop_->runInLoop(

        Boo::绑定(和承认者::听), get_pointer(acceptor_)));

  }

}

void EventLoopThreadPool::start( const ThreadInitCallback& CB) // 翻开线索的方式是应用EntError线索,从此类将是事情环 和 Thread 封装跟在后面 one loop per thread

{

  assert(!started_);

  baseLoop_->assertInLoopThread();

  started_ = true;

  for (int i = 0; i < numThreads_; ++i)

  {

    EventLoopThread* t = new EventLoopThread(CB); // 设置线索 callback

    (t); 

    (t->startLoop()); // 保鲜环办理和分派苦差事,苦差事分派实际的是经过EngCurr:: 来停止的

  }

  if (numThreads_ == 0 && CB)

  {

    cb(baseLoop_);

  }

}

  总结一下,嗨同一的的起反应的人是轮询器的构架。,这是第每一相识的人的。,符合事情监控和散布的头部者。主宰事情环的构架。

  在四周制作节目8,最好的每一类保鲜事情环。,就是,只使成为EVENTROL环。,从此返乡是起反应的人,停止线索 它是经过线索池造成的。,从此,最好的每一线索说出来源起反应的人中以使筋疲力尽I/O。,停止线索用于使筋疲力尽计算苦差事。,从此,该用模子做符合的计算密集队,而不是I/O密集队。。

  制作节目9,有多个起反应的人,朝内的,次要 reactor 牧草感觉器官,特于监督3.5个事情说话中肯衔接。,音讯抵达和衔接断开和音讯发送事情 起反应的人使筋疲力尽。因尽 reactor 只关注扩大事情的衔接,能恰当的IO请的高被附加性,多个起反应的人的在也可以思索I/O和,因而它被以为是能力更强的的处理制作节目。。

他日,朕将相识的人更多的上木渎广泛分布书屋的使满意。,包含起反应的人构架的使容易,线索池的造成,同辈人C的笔墨文字,用C 11重写等。现时它演出像C 11 thread library 所储备物质的电话话筒大部分地可以被掉换。 posix thread library,不在乎本质可以经过POSIX 线索造成,究竟,Linux内核曾经修正了NPTL。。C++11 储备物质了 thread_local 来描画 线索使分裂内存,只因为没pthRead电键使成为 储备物质 析构重大聚会,或许在需求应用TLS的时辰应用POSIX。 储备物质的电话话筒。

Muduo 多线索 线索池 reactor