muduo网络库源码复现笔记(十七):什么都不做的EventLoop

Muduo网络库简介

muduo 是一个基于 Reactor 模式的现代 C++ 网络库,作者陈硕。它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。
muduo网络库的核心代码只有数千行,在网络编程技术学习的进阶阶段,muduo是一个非常值得学习的开源库。目前我也是刚刚开始学习这个网络库的源码,希望将这个学习过程记录下来。这个网络库的源码已经发布在GitHub上,可以点击这里阅读。目前Github上这份源码已经被作者用c++11重写,我学习的版本是没有使用c++11版本的。不过二者大同小异,核心思想是没有变化的。点这里可以看我的源代码。从笔记十七开始记录muduo的net库的实现过程。如果你需要看一下基础库(base)的复现过程,可以点击这里:muduo的base库实现过程

什么都不做的EventLoop

muduo网络库采用的是one loop per thread + threadpool的模式,也就是说主线程属于main loop,创建listenfd,创建listenfd的可读回调函数,该回调函数执行accept返回交流套接字,同时new一个http对象(与交流套接字绑定),添加进thread loop,从此这个交流套接字由thread loop负责,在thread loop中进行客户端和服务端的交流。
EventLoop就是这样的事件处理对象,每个线程仅能创建一个EventLoop。创建了EventLoop对象的线程称为IO线程,功能是运行事件循环。
EventLoop的实现比较复杂,今后的博客将一步步实现的。今天先简单讲解一些EventLoop对象的一些公开接口,所以今天的标题是“什么都不做的EventLoop”。

EventLoop类

如前所述,Event类的特征是不可拷贝、每个线程仅能创建一个、接口不可跨线程调用。让我们看看它的这些缺点是如何实现的。

class EventLoop : boost::noncopyable
{
public:
	EventLoop();
	~EventLoop();
	
	void loop();
	
	void assertInLoopThread()
	{
		if(!isInLoopThread())
		{
			abortNotInLoopThread();
		}
	}
	bool isInLoopThread() const {return threadId_ == CurrentThread::tid();}

	static EventLoop* getEventLoopOfCurrentThread();
private:
	void abortNotInLoopThread();
	bool looping_;
	const pid_t threadId_;
};

EventLoop构造函数与析构函数

为了保证EventLoop在每个线程中仅有一个,在EventLoop.cc中定义了一个线程局部变量__thread EventLoop* t_loopInThisThread = 0;当EventLoop对象创建时,将它赋值this指针;若在一个线程中再创建一个EventLoop,这时t_loopInThisThread不为空,出现fatal。同时创建对象时,初始化了本线程的线程号threadId_。

EventLoop::EventLoop()
	:	looping_(false),
		threadId_(CurrentThread::tid())
{
	LOG_TRACE<< "EventLoop created" << this << "in thread" << threadId_;
	if(t_loopInThisThread)
	{
		LOG_FATAL<<"Another EventLoop" << t_loopInThisThread
				<< "exsits in this thread" << threadId_;	
	}
	else
	{
		t_loopInThisThread = this;
	}
}

EventLoop::~EventLoop()
{
	t_loopInThisThread = NULL;
}

loop函数

loop的作用就是执行事件循环,进行客户与服务端的交流。当前的loop还比较简单,我们仅用它阻塞5秒钟。前面说过loop函数不可跨线程调用,也就是说假如你在主线程创立一个全局EventLoop,然后在另一个线程中调用它的loop,将会出现错误。assertInLoopThread()将会检查创立时的线程号与当前线程号是否一致,如果不一致,会出现fatal。

void EventLoop::loop()
{
	assert(!looping_);
	assertInLoopThread();
	looping_ = true;
	LOG_TRACE << "EventLoop" << this << "start looping";

	::poll(NULL,0,5*1000);
	
	LOG_TRACE << "EventLoop" << this << "stop looping";
	looping_ = false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值