• muduo源码剖析之EventLoopThreadPool


    简介

    EventLoopThreadPool是EventLoopThread类的线程池类

    封装了若干个EventLoopThread的线程池,所有者是一个外部的EventLoop

    EventLoopThreadPool == EventLoopThread + vector

    主要成员及属性解析

    通过调用start函数来new EventLoopThread创建对应的线程和其loop,并将创建的保存在vector中

    源码剖析

    这个类比较简单,代码都写了注释,不多说

    EventLoopThreadPool.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 an internal header file, you should not include this.
     
    #ifndef MUDUO_NET_EVENTLOOPTHREADPOOL_H
    #define MUDUO_NET_EVENTLOOPTHREADPOOL_H
     
    #include "muduo/base/noncopyable.h"
    #include "muduo/base/Types.h"
     
    #include 
    #include 
    #include 
     
    namespace muduo
    {
     
    namespace net
    {
     
    class EventLoop;
    class EventLoopThread;
     
    class EventLoopThreadPool : noncopyable
    {
     public:
      typedef std::function<void(EventLoop*)> ThreadInitCallback;
     
      EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg);
      ~EventLoopThreadPool();
        
      //设置subloop的数量
      void setThreadNum(int numThreads) { numThreads_ = numThreads; }
      //线程池启动,会创建设置好的EventLoopThread数量,并保存threads_中
      void start(const ThreadInitCallback& cb = ThreadInitCallback());
     
      // valid after calling start()
      /// round-robin
      //通过next变量保存下标,每调用一次就会获取下一个loop
      EventLoop* getNextLoop();
     
      /// with the same hash code, it will always return the same EventLoop
      //使用相同的哈希码,它将始终返回相同的事件循环,
      //通过hash码获取相应的loop
      EventLoop* getLoopForHash(size_t hashCode);
     
      //获取所有的subloop
      std::vector<EventLoop*> getAllLoops();
     
      bool started() const
      { return started_; }
     
      const string& name() const
      { return name_; }
     
     private:
     
      EventLoop* baseLoop_;     //主线程的事件驱动循环,TcpServer所在的事件驱动循环,创建TcpServer传入的EventLoop
      string name_;
      bool started_;//线程池启动标志
      int numThreads_;          //线程数 
      int next_;                //标记下次应该取出哪个线程,采用round_robin
      std::vector<std::unique_ptr<EventLoopThread>> threads_;     //线程池中所有的线程 
      //线程池中每个线程对应的事件驱动循环,从线程池取出线程实际上返回的是事件驱动循环
      //每个事件驱动循环运行在一个线程中
      std::vector<EventLoop*> loops_;
    };
     
    }  // namespace net
    }  // namespace muduo
     
    #endif  // MUDUO_NET_EVENTLOOPTHREADPOOL_H
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    EventLoopThreadPool.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/EventLoopThreadPool.h"
     
    #include "muduo/net/EventLoop.h"
    #include "muduo/net/EventLoopThread.h"
     
    #include 
     
    using namespace muduo;
    using namespace muduo::net;
     
    //EventLoopThreadPool loop对应的线程池
    EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg)
      : baseLoop_(baseLoop),//设置mainloop
        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(!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_);
      }
    }
     
    EventLoop* EventLoopThreadPool::getNextLoop()        //获取一个线程(事件驱动循环),通常在创建TcpConnection时调用 
    {
      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* EventLoopThreadPool::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_;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
  • 相关阅读:
    BUG记录-窗体初始化时无法正确获取控件大小
    JavaScriptJQuery_jQuery CSS样式操作
    前端面试问题汇总 - 工程管理工具篇
    vue3如何打开页面即向后端发送请求
    公司企业端口映射
    单链表反转(acm模式)删除重复元素
    DevExpress FMX Data Grid全面编辑和定制
    Git 提交时忽略某些文件
    【vue】elmentUI封装自定义表单组件
    代理IP与Socks5代理的多重应用
  • 原文地址:https://blog.csdn.net/weixin_50448879/article/details/134022013