Condition的含义是条件变量,其实现依赖于系统,一般都要配合Mutex使用,使用步骤为:给mutex上锁(Lock),调用wait等待“条件”发生,如果没有发生则re-wait(),最后释放mutex(unlock),并继续执行。所有等待(wait)同一个“条件变量(condition)”的线程都要使用相同的一把锁——这样相当于互斥操作该Condition。
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
/*
* Condition variable class. The implementation is system-dependent.
*
* Condition variables are paired up with mutexes. Lock the mutex,
* call wait(), then either re-wait() if things aren't quite what you want,
* or unlock the mutex and continue. All threads calling wait() must
* use the same mutex for a given Condition.
*/
class Condition {
public:
enum {
PRIVATE = 0,//指定释放跨进程共享
SHARED = 1
};
Condition();
Condition(int type);
~Condition();
// Wait on the condition variable. Lock the mutex before calling.
status_t wait(Mutex& mutex);//通过Mutex来对“条件变量”实现互斥访问——多线程、多进程场景
// same with relative timeout
status_t waitRelative(Mutex& mutex, nsecs_t reltime);
// Signal the condition variable, allowing one thread to continue.
void signal();
// Signal the condition variable, allowing all threads to continue.
void broadcast();
private:
#if defined(HAVE_PTHREADS)
pthread_cond_t mCond;//Linux的pthread_cond_t类型
#else
void* mState;
#endif
};
// ---------------------------------------------------------------------------
#if defined(HAVE_PTHREADS)
inline Condition::Condition() {
pthread_cond_init(&mCond, NULL);
}
inline Condition::Condition(int type) {
if (type == SHARED) {
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&mCond, &attr);
pthread_condattr_destroy(&attr);
} else {
pthread_cond_init(&mCond, NULL);
}
}
inline Condition::~Condition() {
pthread_cond_destroy(&mCond);
}
inline status_t Condition::wait(Mutex& mutex) {//系统调用wait包含:释放锁、进入休眠等待、唤醒后重新获取锁
return -pthread_cond_wait(&mCond, &mutex.mMutex);
}
inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {//具有时间控制
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
struct timespec ts;
ts.tv_sec = reltime/1000000000;
ts.tv_nsec = reltime%1000000000;
return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
struct timespec ts;
#if defined(HAVE_POSIX_CLOCKS)
clock_gettime(CLOCK_REALTIME, &ts);
#else // HAVE_POSIX_CLOCKS
// we don't support the clocks here.
struct timeval t;
gettimeofday(&t, NULL);
ts.tv_sec = t.tv_sec;
ts.tv_nsec= t.tv_usec*1000;
#endif // HAVE_POSIX_CLOCKS
ts.tv_sec += reltime/1000000000;
ts.tv_nsec+= reltime%1000000000;
if (ts.tv_nsec >= 1000000000) {
ts.tv_nsec -= 1000000000;
ts.tv_sec += 1;
}
return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
}
inline void Condition::signal() {
pthread_cond_signal(&mCond);
}
inline void Condition::broadcast() {
pthread_cond_broadcast(&mCond);
}
#endif // HAVE_PTHREADS
// ---------------------------------------------------------------------------
}; // namespace android
Barrier是利用上面Condition的一个例子:
class Barrier
{
public:
inline Barrier() : state(CLOSED) { }//state就是所谓的“条件”
inline ~Barrier() { }
void open() {
Mutex::Autolock _l(lock);
state = OPENED;
cv.broadcast();
}
void close() {
Mutex::Autolock _l(lock);
state = CLOSED;
}
void wait() const {
Mutex::Autolock _l(lock);//临时对象_l,用lock来构造,在AutoLock的构造函数里已给lock加锁(调用lock()函数)——该wait()函数执行完毕,会自动释放lock(这个场景会使得其他线程再次修改state,产生不安全因素。不过由于Barrier的使用场景的特殊性,其用在线程初始化时,故OK。)
while (state == CLOSED) {//while语句:不断轮询,直到state==OPENED
cv.wait(lock);
}
}
private:
enum { OPENED, CLOSED };
mutable Mutex lock;//持有一个互斥锁
mutable Condition cv;//持有一个条件变量
volatile int state;//每次都从内存更新的“条件”
};