首页 > 其他分享 >【muduo】net篇---EventLoopThread和EventLoopThreadPool

【muduo】net篇---EventLoopThread和EventLoopThreadPool

时间:2023-08-29 12:33:40浏览次数:31  
标签:baseLoop EventLoopThread EventLoop --- _. 线程 net loop


EventLoopThread是事件循环线程,包含一个Thread对象,一个EventLoop对象。在构造函数中,把EventLoopThread::threadFunc 注册到Thread对象中(线程启动时会回调)。

EventLoopThreadPool是事件循环线程池,管理所有客户端连接,每个线程都有唯一一个事件循环。可以调用setThreadNum设置线程的数目。

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

using namespace muduo;
using namespace muduo::net;

/******************************************************************** 
Modify : Eric Lee
Date : 2018-01-21
Description : 这个类专门创建一个线程用于执行Reactor的事件循环,当然
这只是一个辅助类,没有说一定要使用它,可以根据自己的情况进行选择,
你也可以不创建线程去执行事件循环,而在主线程中执行事件循环,
一切根据自己的需要。

EventLoopThread(也叫IO线程)的工作流程为:
1、在主线程(暂且这么称呼)创建EventLoopThread对象。 
2、主线程调用EventLoopThread.start(),启动EventLoopThread中的线程
(称为IO线程),这是主线程要等待IO线程创建完成EventLoop对象。 
3、IO线程调用threadFunc创建EventLoop对象。通知主线程已经创建完成。 
4、主线程返回创建的EventLoop对象。
*********************************************************************/
EventLoopThread::EventLoopThread(const ThreadInitCallback& cb,
                                 const string& name)
  : loop_(NULL),
    exiting_(false),
    thread_(std::bind(&EventLoopThread::threadFunc, this), name),
    mutex_(),
    cond_(mutex_),
    callback_(cb)
{
}

EventLoopThread::~EventLoopThread()
{
  exiting_ = true;
  if (loop_ != NULL)
  {
    loop_->quit();
    thread_.join();
  }
}

/******************************************************************** 
Modify : Eric Lee
Date : 2018-01-16
Description : 启动一个EventLoop线程。
*********************************************************************/
EventLoop* EventLoopThread::startLoop()
{
  assert(!thread_.started());
  // 当前线程启动,调用threadFunc()
  thread_.start();
  EventLoop* loop = NULL;
  {
    MutexLockGuard lock(mutex_);
    while (loop_ == NULL)
    {
      // 等待创建好当前IO线程
      cond_.wait();
    }
    loop = loop_;
  }
  return loop;
}

void EventLoopThread::threadFunc()
{
  EventLoop loop;
  // 如果有初始化函数,就先调用初始化函数
  if (callback_)
  {
    callback_(&loop);
  }
  {
    MutexLockGuard lock(mutex_);
    loop_ = &loop;
    // 通知startLoop线程已经启动完毕
    cond_.notify();
  }
  // 事件循环
  loop.loop();
  MutexLockGuard lock(mutex_);
  loop_ = NULL;
}
#include <muduo/net/EventLoopThreadPool.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/EventLoopThread.h>

#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

/******************************************************************** 
Modify : Eric Lee
Date : 2018-01-21
Description : eventloopthreadpool是基于muduo库中Tcpserver这个类专门
做的一个线程池,它的模式属于半同步半异步,线程池中每一个线程都有一个
自己的eventloop,而每一个eventloop底层都是一个poll或者epoll,它利用了
自身的poll或者epoll在没有事件的时候阻塞住,在有事件发生的时候,epoll
监听到了事件就会去处理事件。
*********************************************************************/
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
}

/******************************************************************** 
Modify : Eric Lee
Date : 2018-01-21
Description : 启动EventLoop线程池。
*********************************************************************/
void EventLoopThreadPool::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);
    // 创建一个EventLoop线程
    EventLoopThread* t = new EventLoopThread(cb, buf);
    // 放入threads_(EventLoop线程池)
    threads_.push_back(std::unique_ptr<EventLoopThread>(t));
    // 启动每个EventLoopThread线程进入startLoop(),并且把返回的每个EventLoop指针压入到loops_
    loops_.push_back(t->startLoop());
  }
  if (numThreads_ == 0 && cb)
  {
    // 只有一个EventLoop,在这个EventLoop进入事件循环之前,调用cb
    cb(baseLoop_);
  }
}

/******************************************************************** 
Modify : Eric Lee
Date : 2018-01-21
Description : 使用round-robin(轮询调度)算法,从EventLoop线程池中
选择一个EventLoop。
*********************************************************************/
EventLoop* EventLoopThreadPool::getNextLoop()
{
  baseLoop_->assertInLoopThread();
  assert(started_);
  EventLoop* loop = baseLoop_;
  /************************************************************************ 
  轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1
  开始,直到N(内部服务器个数),然后重新开始循环。轮询调度算法假设所有服务器
  的处理性能都相同,不关心每台服务器的当前连接数和响应速度。当请求服务间隔
  时间变化比较大时,轮询调度算法容易导致服务器间的负载不平衡。
  *************************************************************************/
  if (!loops_.empty())
  {
    // round-robin(轮询调度),next_记录的是下一个空闲的EventLoop。
    loop = loops_[next_];
    ++next_;
    if (implicit_cast<size_t>(next_) >= loops_.size())
    {
      next_ = 0;
    }
  }
  return loop;
}

/******************************************************************** 
Modify : Eric Lee
Date : 2018-01-21
Description : 通过哈希法从EventLoop线程池中选择一个EventLoop。
*********************************************************************/
EventLoop* EventLoopThreadPool::getLoopForHash(size_t hashCode)
{
  baseLoop_->assertInLoopThread();
  EventLoop* loop = baseLoop_;
  if (!loops_.empty())
  {
    loop = loops_[hashCode % loops_.size()];
  }
  return loop;
}

/******************************************************************** 
Modify : Eric Lee
Date : 2018-01-21
Description : 获得所有的EventLoop。
*********************************************************************/
std::vector<EventLoop*> EventLoopThreadPool::getAllLoops()
{
  baseLoop_->assertInLoopThread();
  assert(started_);
  if (loops_.empty())
  {
    return std::vector<EventLoop*>(1, baseLoop_);
  }
  else
  {
    return loops_;
  }
}


标签:baseLoop,EventLoopThread,EventLoop,---,_.,线程,net,loop
From: https://blog.51cto.com/u_6526235/7274952

相关文章

  • 【muduo】net篇---TcpServer
    TcpServer在创建的过程中,首先new出来自己的核心组件(Acceptor,loop,connectionMap,threadPool)之后TcpServer会向Acceptor注册一个新连接到来时的Connection回调函数。一旦接受到一个client的连接,就会调用TcpServer::newConnection()函数。这个函数使用round-robin算法从EventLoopThr......
  • 【muduo】net篇---EventLoop
    EventLoop类调用Poller::poll()进行I/O复用,返回活跃事件列表,然后遍历该列表,依次调用每一个活跃Channel的事件处理函数handleEvent(),最终回调了TcpConnection注册过来的函数。#include<muduo/net/EventLoop.h>#include<muduo/base/Logging.h>#include<muduo/base/Mutex.h>#inc......
  • 【muduo】net篇---Poller
    Poller类负责更新某一个Channel(或者说套接字)上对应的事件,通过epoll_wait()函数返回有事件发生的套接字,设置Channel上的事件(revents_),并添加到激活事件列表中。#include<muduo/net/poller/EPollPoller.h>#include<muduo/base/Logging.h>#include<muduo/net/Channel.h>#include......
  • 论文阅读 《Pingmesh: A Large-Scale System for Data Center Network Latency Measur
    背景在我们内部产品中,一直有关于网络性能数据监控需求,我们之前是直接使用ping命令收集结果,每台服务器去ping(N-1)台,也就是N^2的复杂度,稳定性和性能都存在一些问题,最近打算对这部分进行重写,在重新调研期间看到了Pingmesh这篇论文,Pingmesh是微软用来监控数据中心网络情况......
  • 2023年DAMA-CDGA/CDGP数据治理认证线上到这里学习
    DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业竞争能力。DAMA是数据管理方面的认证,帮助数据从业者提升......
  • 2023年9月DAMA-CDGA/CDGP数据治理认证考试,火热报名
    据DAMA中国官方网站消息,2023年度第三期DAMA中国CDGA和CDGP认证考试定于2023年9月23日举行。 报名通道现已开启,相关事宜通知如下: 考试科目: 数据治理工程师(CertifiedDataGovernanceAssociate,CDGA)数据治理专家(CertifiedDataGovernanceProfessional,CDGP) 考试时间: CDGA:2023......
  • iTOP-i.MX8MM开发板添加RIL驱动程序库
    将Quectel提供的相应RIL库文件放入Android系统的以下路径。作者拷贝到了源码的android_build/device/fsl/imx8m/evk_8mm/lib目录下,如下图所示:然后将apns-conf.xml拷贝到android_build/device/fsl/imx8m/evk_8mm/下,如下图所示:......
  • 智能菜谱系统-计算机毕业设计源码+LW文档
    1.1研究背景自古以来,烹饪食品一直是人类的基本需求之一,烹饪技术的不断发展和创新,为人们带来了不同的美食体验。科技进步的同时又在不断地加快人们的生活节奏,越来越忙碌的生活节奏使得人们能够花费在制作美食上的时间越来越少;同时,随着生活水平的提高,人们对健康饮食的需求也日益增长......
  • 幼儿园管理系统-计算机毕业设计源码+LW文档
    摘 要现在人们对学前教育越来越重视,幼儿教育发展迅速,幼儿的数量也在大大增加,导致幼儿园的管理工作变得愈加繁重。以报表的方式管理幼儿园信息资料,不仅不方便园中资料的存储和查看,还加重了园中的管理工作、减低了工作效率。现在,大多数幼儿园都缺少一个向外界展现自身特色的平台,幼......
  • Flutter系列文章-Flutter在实际业务中的应用
    不同场景下的解决方案1.跨平台开发:在移动应用开发中,面对不同的平台(iOS和Android),我们通常需要编写两套不同的代码。而Flutter通过一套代码可以构建适用于多个平台的应用,大大提高了开发效率,降低了维护成本。2.混合开发:在一些已有的原生应用中,引入Flutter可以用于开发某些特定......