Condition类图
-------------------------------------------------------
Condition
--------------------------
-mutex_:MutexLock& //不负责MutexLock的生命周期
-pcond:pthread_cond_t //条件变量
--------------------------
<<create>>-condition(mutex:MutexLock&)
<<destroy>>-Condition
+wait():void //等待函数
+waitForSeconds(seconds:int) : bool //等待函数
+notify():void //信号函数
+notifyAll():void//信号函数
-------------------------------------------------------
Condition的头文件
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_CONDITION_H
#define MUDUO_BASE_CONDITION_H
#include <muduo/base/Mutex.h>
#include <boost/noncopyable.hpp>
#include <pthread.h>
namespace muduo
{
/*
Condition 不负责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());
}
// returns true if time out, false otherwise.
bool waitForSeconds(int seconds);
void notify()
{//发送条件变量
pthread_cond_signal(&pcond_);
}
void notifyAll()
{ //广播条件变量
pthread_cond_broadcast(&pcond_);
}
private:
MutexLock& mutex_;
pthread_cond_t pcond_;
};
}
#endif // MUDUO_BASE_CONDITION_H
condition的源代码
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#include <muduo/base/Condition.h>
#include <errno.h>
// returns true if time out, false otherwise.
bool muduo::Condition::waitForSeconds(int seconds)
{
struct timespec abstime;
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_sec += seconds;
return ETIMEDOUT == (&pcond_, mutex_.getPthreadMutex(), &abstime);
}
CountDownLatch类图
---------------------------------------
-mutex_:MutexLock
-condition_:Condition
-count_: int
------------------------
<<create>>-CoutDownLatch(count:int)
+wait():void
+coutDown():void
+getCount():int
-------------------------------------------
既可以用于所有子线程等待主线程发起“起跑”
也可以用于主线程等待子线程初始化完毕才开始工作
-------------------------------------------
CountDownLatch头文件
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#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:
mutable MutexLock mutex_; //mutable 可以改变的
Condition condition_; //条件变量类 MutexLock mutex_会传递给condition_
int count_; //计数器,主要用来协程处理
};
}
#endif // MUDUO_BASE_COUNTDOWNLATCH_H
CountDownLatch源文件
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#include <muduo/base/CountDownLatch.h>
using namespace muduo;
CountDownLatch::CountDownLatch(int count) //使用计数器进行初始化
: mutex_(),
condition_(mutex_), //传递给condition类
count_(count)
{
}
/*
等待线程,一直等到条件满足
*/
void CountDownLatch::wait()
{
MutexLockGuard lock(mutex_);
while (count_ > 0) { //等待,muduo 把count_ ==0 才是条件满足,这些我们自己在封装时,可以自己设定该值
condition_.wait();
}
}
/*
减少计算器,逼近条件满足,如果满足则唤醒 “睡眠的线程”
**/
void CountDownLatch::countDown()
{
MutexLockGuard lock(mutex_);
--count_; //
if (count_ == 0) {
condition_.notifyAll();
}
}
/*
获取计算器
**/
int CountDownLatch::getCount() const//正常时候下面变量的状态是不可以被改变的,
//但是mutex被mutable修饰了,所以他的状态是可以被改变的,
//而count_的状态就不可以被改变了
{
MutexLockGuard lock(mutex_);
return count_;
}
测试程序1 :
#include <muduo/base/CountDownLatch.h>
#include <muduo/base/Thread.h>
#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <string>
#include <stdio.h>
/*
该程序的主要功能是:
主线程先创建3个线程,然后线程会等待主线程释放“计数器”,也就是cont_;
主线程休眠3秒钟,然后发布命令(把count_设为0,然后唤醒上面的程序)。
**/
using namespace muduo;
class Test
{
public:
Test(int numThreads): latch_(1), //计算器初始化为1
threads_(numThreads) //线程的个数
{
//创建numthreads个线程,把他们放到容器threads_中
for (int i = 0; i < numThreads; ++i)
{
char name[32];
snprintf(name, sizeof name, "work thread %d", i);
//创建线程,线程的回调函数为Test::threadFunc ,线程会阻塞在该函数中,一直等待count_ == 0
threads_.push_back(new muduo::Thread(boost::bind(&Test::threadFunc, this), muduo::string(name)));
}
//循环启动线程
for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::start, _1));
}
void run()
{ //发布命令,count_ -- = 0
latch_.countDown();
}
//等待线程
void joinAll()
{
for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::join, _1));
}
private:
void threadFunc()
{
//等待count_ 满足条件
latch_.wait();
//成功后运行
printf("tid=%d, %s started\n",
CurrentThread::tid(),
CurrentThread::name());
printf("tid=%d, %s stopped\n",
CurrentThread::tid(),
CurrentThread::name());
}
CountDownLatch latch_; //协程
boost::ptr_vector<Thread> threads_; //线程指针容器
};
int main()
{
//
printf("pid=%d, tid=%d\n", ::getpid(), CurrentThread::tid());
//计算器被设置为
Test t(3);
sleep(3);
printf("pid=%d, tid=%d %s running ...\n", ::getpid(), CurrentThread::tid(), CurrentThread::name());
t.run();
t.joinAll();
printf("number of created threads %d\n", Thread::numCreated());
}
测试程序2
#include <muduo/base/CountDownLatch.h>
#include <muduo/base/Thread.h>
#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <string>
#include <stdio.h>
/**
该程序的主要功能:
主线程创建 3 个线程,协程变量为3 , 主线程阻塞,一直到3个线程依次 count_--,此时count_ ==0 , 主线程
才会被唤醒。
程序1是子线程等待主线程发布命令
程序2是主线程等待子线程“准备好”了,才开始一起运行。
***/
using namespace muduo;
class Test
{
public:
Test(int numThreads)
: latch_(numThreads),
threads_(numThreads)
{
for (int i = 0; i < numThreads; ++i)
{
char name[32];
snprintf(name, sizeof name, "work thread %d", i);
threads_.push_back(new muduo::Thread(
boost::bind(&Test::threadFunc, this), muduo::string(name)));
}
for_each(threads_.begin(), threads_.end(), boost::bind(&muduo::Thread::start, _1));
}
void wait()
{
latch_.wait();
}
void joinAll()
{
for_each(threads_.begin(), threads_.end(), boost::bind(&Thread::join, _1));
}
private:
void threadFunc()
{
sleep(3);
latch_.countDown();
printf("tid=%d, %s started\n",
CurrentThread::tid(),
CurrentThread::name());
printf("tid=%d, %s stopped\n",
CurrentThread::tid(),
CurrentThread::name());
}
CountDownLatch latch_;
boost::ptr_vector<Thread> threads_;
};
int main()
{
printf("pid=%d, tid=%d\n", ::getpid(), CurrentThread::tid());
Test t(3);
t.wait();
printf("pid=%d, tid=%d %s running ...\n", ::getpid(), CurrentThread::tid(), CurrentThread::name());
t.joinAll();
printf("number of created threads %d\n", Thread::numCreated());
}