muduo网络库源码复现笔记(五):base库的Mutex.h和Condition.h和CoutntDownLatch.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
muduo网络库源码复现笔记(四):base库的Thread.h和CurrentThread.h

Mutex.h

熟悉操作系统编程的同学肯定对互斥量mutex不陌生,Mutex.h就是对互斥量mutex的操作做了一些封装,这个头文件里有两个类,分别是MutexLock和MutexGuard类,下面详细看一看。

MutexLock类

MutexLock类的封装很清晰,包括初始化、上锁、解锁、销毁的操作。

class MutexLock : boost::noncopyable
{
public:
	MutexLock():holder_(0)//初始化mutex
	{
		int ret = pthread_mutex_init(&mutex_,NULL);
		assert(ret == 0);(void) ret;
	}
	
	~MutexLock()//销毁mutex
	{
		assert(holder_ == 0);
		int ret = pthread_mutex_destroy(&mutex_);
		assert(ret == 0);(void)ret;
	}
	
	bool isLockedByThisThread()
	{
		return holder_ == CurrentThread::tid();
	}
	
	bool assertLocked()
	{
		assert(isLockedByThisThread());
	}
	
	void lock()//上锁
	{
		pthread_mutex_lock(&mutex_);
		holder_ = CurrentThread::tid();
	}
	
	void unlock()//解锁
	{
		holder_ = 0;
		pthread_mutex_unlock(&mutex_);
	}

	pthread_mutex_t* getPthreadMutex()
	{
		return &mutex_;
	}
private:
	pthread_mutex_t mutex_;
	pid_t holder_;
};

MutexGuard类

MutexGurad类是对MutexLock类的又一层封装,主要实现的是Mutex的管理。
这个类很简单,唯一需要注意的是这个类的私有变量MutexLock是一个引用,所以当MutexGuard的对象生命周期结束时,mutex的生命周期并没有结束,即MutexGurad不能左右他所管理的Mutex的生命周期

class MutexLockGuard : boost::noncopyable
{
public:
	explicit MutexLockGuard(MutexLock &mutex)
	: mutex_(mutex)
	{
		mutex_.lock();
	}

	~MutexLockGuard()
	{
		mutex_.unlock();
	}
private:
	MutexLock &mutex_;
};

Condition.h

Condition.h是对Linux下的条件量的封装,包括初始化、等待操作、唤醒线程操作、销毁操作。条件量通常和互斥量一起协同控制线程。这个类同样也很简单,私有变量mutex同样也是引用类型。

class Condition : boost::noncopyable
{
public:
	explicit Condition(MutexLock& mutex):mutex_(mutex)//初始化
	{
		pthread_cond_init(&pcond_,NULL);
	}

	~Condition()//销毁
	{
		pthread_cond_destroy(&pcond_);
	}

	void wait()//阻塞等待
	{
		pthread_cond_wait(&pcond_,mutex_.getPthreadMutex());
	}

	bool waitForSeconds(int seconds);
	
	void notify()//唤醒一个随机线程
	{
		pthread_cond_signal(&pcond_);
	}

	void notifyAll()//唤醒所有线程
	{
		pthread_cond_broadcast(&pcond_);
	}

private:
	MutexLock& mutex_;
	pthread_cond_t pcond_;
};

CountDownLatch.h

CountDownLatch.h包含的是CountDownLatch类。这个类是对互斥量与条件量的又一次封装。它的私有变量有三个,分别是互斥量mutex_、条件量condition_、计数器count。mutex_有一个修饰词mutable,故mutex_可以在被const修饰的函数内发生修改,count协同条件量工作,具体看下面函数类的讲解

class CountDownLatch : boost::noncopyable
{
public:
	explicit CountDownLatch(int count);

	void wait();
	
	void countDown();

	int getCount() const;//返回count_

private:
	mutable MutexLock mutex_;
	Condition condition_;
	int count_;	
};

构造函数CountDownLatch(int count)

这个函数很简单,列表初始化了三个私有成员,需要注意一下就是mutex_和condition_是外部类类型,必需用列表初始化的方式初始化

CountDownLatch::CountDownLatch(int count)
:mutex_(),condition_(mutex_),count_(count)
{
	
}

线程等待函数 wait()

我们以往我们在使用互斥量的时候,往往把它视作一个值,lock操作就是减一,unlock就是加一。实际上互斥量是一个结构体,这里count帮助互斥量用于计数,我们不必再把互斥量视作一个值。在wait函数中,当count大于0时,线程进入阻塞等待状态。

void CountDownLatch::wait()
{
	MutexLockGuard lock(mutex_);
	while(count_ > 0)
	{
		condition_.wait();
	}
}

Count减操作 countDown()

countDown()和wait()可以协同工作,在countDown中,lock拿到锁之后,对count进行减操作,如果count为零,就唤醒所有线程。

void CountDownLatch::countDown()
{
	MutexLockGuard lock(mutex_);
	--count_;
	if(count_ == 0)
	{
		condition_.notifyAll();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值