Muduo网络库的实现EventLoop class (一)

源码下载以及安装点击链接https://blog.csdn.net/YoungSusie/article/details/90021742

分类 Muduo网络库编程 学习笔记

muduo网络库采取的模式为: one loop per thread + thread pool

0、什么都不用做的EventLoop class

one loop per thread 每个线程只能由一个EventLoop对象,其构造函数会用__thread 类型的变量记住本对象所属的线程ID。
创建了EventLoop 对象的线程是IO线程,其主要功能是运行事件循环loop(),事件循环 必须在IO线程执行。此对象的生命期与线程一样长。

1、学习笔记

  1. 如何返回线程ID gettid()?

虽然 threads 库提供了pthread_self()
函数返回当前线程的ID,线程ID类型为pthread_t。这里有两个问题:一个是,pthread_t类型无法输出、比较、只在进程内有意义,与操作系统的任务调度之间无法建立有效关联;同时,glibc实现上将pthread_t 用做一个结构体指针,指向动态内存,切该内存会反复使用,只能保证同一时刻同一进程各个线程的ID不同,不能保证同一进程先后多个线程ID不同。因此此函数与返回值类型不适合作为线程的标识符。

可以使用gettid() 系统调用,但是需要注意的是,Glibc并没有提供此接口的声明,此接口实际使用的是系统调用,使用者可以自己创建包裹函数

包裹此函数,并用pid_t 类型作为返回值类型,需要包含头文件#include <sys/types.h> #include <sys/syscall.h>

#include <sys/types.h>
#include <sys/syscall.h>
pid_t gettid()
{
          return static_cast<pid_t>(syscall( __NR_gettid));
}	

其次还需要注意: 由于本项目的很多地方需要用到这个函数,因此在头文件中声明了该函数,但是不可在头文件中定义此函数,会造成重复定义,即使用了ifndef ,(目前我还不知道为什么)。因此我将该函数的定义放在另外一个gettid.cc文件中。

进程ID 和线程ID 的区别可见连接https://blog.csdn.net/YoungSusie/article/details/91973997

  1. 前向声明
    muduo头文件中使用了向前声明,大大简化了头文件之间的依赖关系。 例如,Poller class, Channel class 都向前声明了EventLoop class,从而避免了包含EventLoop.h 头文件

2、代码

==================================EventLoop.h ====================================

#ifndef _EVENTLOOP_
#define _EVENTLOOP_

#include <boost/noncopyable.hpp>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <iostream>


pid_t gettid(void);

class EventLoop : boost::noncopyable
{
  public:
	EventLoop();
	~EventLoop();

	void loop();

        /*void assertInLoopThread()
  	{
   	    if (!isInLoopThread())
   	    {
    		 abortNotInLoopThread();
    	    }
        }*/


	bool isInLoopThread() const
	{
	   
	    return threadId_ == gettid();
	}
  private:
//	void abortNotInLoopThread;
	bool looping_;
	 pid_t threadId_;
};

#endif

	    

================================== EventLoop.cc =====================================

#include "EventLoop.h"

#include <assert.h>
#include <poll.h>


using namespace std;


__thread EventLoop * t_LoopInThisThread = 0;

EventLoop::EventLoop()
	:looping_(false),threadId_(gettid())
{
	
	cout << "EventLoop created" << this << " in thread " << threadId_ << "\n";
	t_LoopInThisThread = this;
}

EventLoop::~EventLoop()
{
	assert(!looping_);
	t_LoopInThisThread = NULL;
}

void EventLoop::loop()
{
	assert(!looping_);
	looping_ = true;
	::poll(NULL,0,5*1000);
	looping_ = false;
}


=================================== gettid.cc =======================================

#include "EventLoop.h"

pid_t gettid()
{
          return static_cast<pid_t>(syscall( __NR_gettid));
}	

=================================== Makefile =======================================

LIB_SRC =  EventLoop.cc gettid.cc
BINARIES = test1 
all: $(BINARIES)

CXXFLAGS = -O0 -g  -Wall -I  -pthread

LDFLAGS = -lpthread


$(BINARIES):
	g++ $(CXXFLAGS) -o $@ $(LIB_SRC) $(filter %.cc,$^) $(LDFLAGS)   // $^--所有的依赖文件   $@--目标文件  $<--第一个依赖文件

clean:
	rm -f $(BINARIES) core

test1: test1.cc
	

分类 Muduo网络库编程 学习笔记

本文摘自陈硕老师的linux多线程服务端编程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值