condition类是封装了条件变量的操作,我以前在做服务器项目的时候也实现过封装condition。
它的实现如下:
#ifndef MUDUO_BASE_CONDITION_H
#define MUDUO_BASE_CONDITION_H
#include <muduo/base/Mutex.h>
#include <boost/noncopyable.hpp>
#include <pthread.h>
namespace muduo
{
class Condition : boost::noncopyable
{
public:
explicit Condition(MutexLock& mutex)
: mutex_(mutex)
{
MCHECK(pthread_cond_init(&pcond_, NULL)); //初始化
}
~Condition()
{
MCHECK(pthread_cond_destroy(&pcond_)); //销毁
}
void wait() //pthread_cond_wait
{
MutexLock::UnassignGuard ug(mutex_);
MCHECK(pthread_cond_wait(&pcond_, mutex_.getPthreadMutex()));
}
// returns true if time out, false otherwise.
bool waitForSeconds(double seconds);
void notify()
{
MCHECK(pthread_cond_signal(&pcond_)); //一对一
}
void notifyAll()
{
MCHECK(pthread_cond_broadcast(&pcond_)); //广播
}
private:
MutexLock& mutex_;
pthread_cond_t pcond_;
};
}
#endif // MUDUO_BASE_CONDITION_H
我们有时对Condition类上面再套一层封装来使用,他就是我们的CountDownLatch类。通过倒计时计数器的方式,设置计数。倒计时未完,CountDownLatch的内部一直处于
Condition类的wait()状态。倒计时完毕,唤醒cond,程序正常执行。所以我们可以给某件即将发生的事设置一个条件,比如至少5个满足才会触发该事件,那么计数值设为5,
等到倒计时为0时,CountDownLatch类就可以让你顺利的去执行该事件了。
所以它主要有两个用法:
1.既可以用于所有子线程主动等待主线程发起“起跑”
2.也可以用于主线哼等待子线程初始化完毕才开始工作
它的类图如下:
它的实现如下:
#ifndef MUDUO_BASE_COUNTDOWNLATCH_H
#define MUDUO_BASE_COUNTDOWNLATCH_H
#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <boost/noncopyable.hpp>
namespace muduo
{
class CountDownLatch : boost::noncopyable
{
public:
explicit CountDownLatch(int count); //传递一个计数器
void wait();
void countDown();
int getCount() const;
private: //CountDownLatch由一把锁,条件变量,计数器构成
mutable MutexLock mutex_;
Condition condition_;
int count_;
};
}
#endif // MUDUO_BASE_COUNTDOWNLATCH_H
以及:
#include <muduo/base/CountDownLatch.h>
using namespace muduo;
CountDownLatch::CountDownLatch(int count)
: mutex_(),
condition_(mutex_), //初始化,条件变量用成员锁初始化
count_(count)
{
}
void CountDownLatch::wait()
{
MutexLockGuard lock(mutex_);
while (count_ > 0) //只要计数值大于0,CountDownLatch类就不工作,知道等待计数值为0
{
condition_.wait();
}
}
void CountDownLatch::countDown() //倒数,倒计时
{
MutexLockGuard lock(mutex_);
--count_;
if (count_ == 0)
{
condition_.notifyAll();
}
}
int CountDownLatch::getCount() const //获得次数
{
MutexLockGuard lock(mutex_);
return count_;
}