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;//每次都從內存更新的“條件” };