当前位置: 代码迷 >> 综合 >> EventLoopThreadPool
  详细解决方案

EventLoopThreadPool

热度:59   发布时间:2023-12-08 15:53:36.0

事件循环线程池,当需要多线程处理事件时使用。

该类的主要成员是std::vector<std::unique_ptr<EventLoopThread>> threads_,EventLoopThread启动一个线程,在其中运行EventLoop::loop()。先说下EventLoopThread。

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) // 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 is exiting anyway.loop_->quit();thread_.join();}
}EventLoop* EventLoopThread::startLoop()
{assert(!thread_.started());thread_.start();EventLoop* loop = NULL;{MutexLockGuard lock(mutex_);while (loop_ == NULL){cond_.wait();}loop = loop_;}return loop;
}void EventLoopThread::threadFunc()
{EventLoop loop;if (callback_){callback_(&loop);}{MutexLockGuard lock(mutex_);loop_ = &loop;cond_.notify();}loop.loop();//assert(exiting_);MutexLockGuard lock(mutex_);loop_ = NULL;
}

EventLoopThread类的主函数就是EventLoopThread::threadFunc(),在该类中创建了一个EventLoop的栈上对象,并运行EventLoop::loop(),正常情况下,EventLoopThread::threadFunc()永远都不会退出,所以也就不用担心在栈上创建的对象会析构。EventLoopThread::startLoop()返回创建的EventLoop对象的地址,因此使用条件变量来等待线程的创建与运行。

再看EventLoopThreadPool

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(!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()
{baseLoop_->assertInLoopThread();assert(started_);EventLoop* loop = baseLoop_;if (!loops_.empty()){// round-robinloop = 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_;}
}

线程个数的指定不是通过构造函数,而是专门的一个函数

void setThreadNum(int numThreads) { numThreads_ = numThreads; }

EventLoopThreadPool::start()启动numThreads_个事件循环线程。

EventLoopThreadPool::getNextLoop()通过round-robin的方式返回一个EventLoop的实例,依次来为每个EventLoop实例分配任务。如果不存在多线程,那么返回的是主EventLoop实例。

EventLoopThreadPool::getLoopForHash()是以其他的计算方式返回实例,但是muduo库现在并没有使用。

EventLoopThreadPool::getAllLoops()返回所有的EventLoop实例

 

  相关解决方案