muduo网络库源码复现笔记(四):base库的Thread.h和CurrentThread.h

Muduo网络库简介

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

Thread.h

Thread.h是对线程做了一个封装,看一下它的类代码:

class Thread : boost::noncopyable
{
public:
	typedef boost::function ThreadFunc; //定义回调函数
  	explicit Thread(const ThreadFunc&, const string& name = string());
  	~Thread();
	void start(); //开启线程的接口
	int join(); // 

	bool started() const { return started_; }
	pid_t tid() const { return tid_; }
	const string& name() const { return name_; }
	static int numCreated() { return numCreated_.get(); }

private:
	static void* startThread(void* thread);//pthread_create调用的回调函数,调用runInThread
	void runInThread();//调用func_

	bool       started_;
	pthread_t  pthreadId_;
	pid_t      tid_;
	ThreadFunc func_;//真正调用的回调函数
	string     name_;//线程名称

  static AtomicInt32 numCreated_;//统计当前线程数
};

pthreadId_和tid_

pthreadId_是线程ID,但是这个值不是唯一的,在不同进程下的两个线程可能会有同一个线程ID,当出现进程p1中的线程t1要与进程p2中的线程t2通信的情况时,需要一个真实的线程id唯一标识,即tid。glibc没有实现gettid的函数,可以通过linux下的系统调用syscall(SYS_gettid)来获得。

startThread

startThread是创建线程时的回调函数,由start()调用,看一下它的代码:

void* Thread::startThread(void* obj)
{
  Thread* thread = static_cast(obj);
  thread->runInThread();
  return NULL;
}

它的传入参数obj实际上就是this指针,传入的时候先转为泛型指针,然后转回来,调用runInthread()。

CurrentThread.h

CurrentThread.h不是一个类,是muduo下的一个namespace。

__thread修饰的变量

CurrentThread.h中又三个__thread修饰的变量

 extern __thread int t_cachedTid;
 extern __thread char t_tidString[32];
 extern __thread const char* t_threadName;

__thread修饰的变量在每个线程中有独立的实体,各个线程中的变量互不干扰。值得注意的是__thread只能修饰POD类型变量(与C兼容的原始数据)。

pthread_atfork

函数原型

int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

pthread_atfork()在fork()之前调用,当调用fork时,内部创建子进程前在父进程中会调用prepare,内部创建子进程成功后,父进程会调用parent ,子进程会调用child。
使用这个函数的目的是当父进程有多线程时,子进程继承父进程所有的互斥量、读写锁和条件变量的状态,子进程只存在一个线程,它是由父进程中调用fork的线程的副本构成的。如果父进程中的线程占有锁(任一线程),子进程同样占有这些锁,所以要清除锁的状态。

你可能感兴趣的:(muduo,c++,多线程,后端,linux)