muduo的并发模型为one loop per thread+ threadpool。
EventLoopThread是事件循环线程,包含一个Thread对象,一个EventLoop对象。在构造函数中,把EventLoopThread::threadFunc 注册到Thread对象中(线程启动时会回调)。
EventLoopThreadPool是事件循环线程池,管理所有客户端连接,每个线程都有唯一一个事件循环,可以调用setThreadNum设置线程的数目。
EventLoopThreadPool
EventLoopThreadPool是基于muduo库中Tcpserver这个类专门做的一个线程池,它的模式属于半同步半异步,线程池中每一个线程都有一个自己的EventLoop,而每一个EventLoop底层都是一个poll或者epoll,它利用了自身的poll或者epoll在没有事件的时候阻塞住,在有事件发生的时候,epoll监听到了事件就会去处理事件。
EventLoopThreadPool.h
#ifndef MUDUO_NET_EVENTLOOPTHREADPOOL_H
#define MUDUO_NET_EVENTLOOPTHREADPOOL_H
#include "muduo/base/noncopyable.h"
#include "muduo/base/Types.h"
#include <functional>
#include <memory>
#include <vector>
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();
void setThreadNum(int numThreads) {
numThreads_ = numThreads; }
void start(const ThreadInitCallback& cb = ThreadInitCallback());
// valid after calling start()
/// round-robin
EventLoop* getNextLoop();
/// with the same hash code, it will always return the same EventLoop
EventLoop* getLoopForHash(size_t hashCode);
std::vector<EventLoop*> getAllLoops();
bool started() const
{
return started_; }
const string& name() const
{
return name_; }
private:
EventLoop* baseLoop_;//主线程的EventLoop
string name_;
bool started_;
int numThreads_;//线程池中线程的数量
int next_;
std::vector<std::unique_ptr<EventLoopThread>> threads_;//线程保存在vector中
std::vector<EventLoop*> loops_;//每个EventLoopThread线程对应的EventLoop保存在loops_中
};
} // namespace net
} // namespace muduo
#endif // MUDUO_NET_EVENTLOOPTHREADPOOL_H
EventLoopThreadPool.cc
#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;
EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg)
: baseLoop_(baseLoop),
name_(nameArg),
started_(false