MuteLock 使用类来封装该功能时需要注意,该类不支持拷贝构造和赋值。
class MutexLock: boost::noncopyable{ public: // Initialize mutex_ MutexLock():holder_(0){ pthread_mutex_init(&mutex_, NULL); } // Destroy mutex_ ~MutexLock(){ assert(holder_ == 0); pthread_mutex_destroy(&mutex_); } // Check the current thread is locked or not bool isLockedByThisThread(){ return holder_ == CurrentThread::tid(); } // assert is used to debug void assertLocked(){ assert(isLockedByThisThread()); } // Lock the thread // 注意,lock与unlock的调用顺序不能错,否则可能会导致一些不可预料的后果 // 其次,lock与unlock只能在MutexLockGuard中调用 void lock(){ pthread_mutex_lock(&mutex_); holder_ = CurrentThread::tid(); } // Unlock the thread void unlock(){ holder_ = 0; pthread_mutex_unlock(&mutex_); } // Get the mutex pthread_mutex_t* getThreadMutex(){ return &mutex_; } private: pthread_mutex_t mutex_; // The lock pid_t holder_; // Indicates which thread owns the lock ];MutexLockGuard 保证了互斥锁可以正确的使用,
class MutexLockGuard: boost::noncopyable{ public: explicit MutexLockGuard(MutexLock &mutex): mutex_(mutex){ mutex.lock(); } ~MuteLockGuard(){ mutex_.unlock(); } private: MutexLock& mutex_; }; // 防止MutexLockGuard 临时变量的产生,其会锁住临界区,但又会随即释放临界区的锁,造成性能浪费等问题 #define MutexLockGuard(x) static_assert(false, "missing mutex guard var name") // 为何不使用assert的原因,在与assert在release中为空语句,为了避免 // 这种问题,因此使用c++11中的static_assert,在编译器解决问题Condition 封装了Pthreads condition variable
class Condition: boost noncopyable{ explicit Condition(MutexLock &mutex): mutex_(mutex){ pthread_cond_init(&pcond_, NULL); } ~Condition(){ pthread_cond_destroy(&pcond_); } void wait(){ pthread_cond_wait(&pcond_, mutex_.getPthreadMutex()); } void notify(){ pthread_cond_signal(&pcond_); } void notifyAll(){ pthread_cond_broadcast(&pcond_); } private: MutexLock &mutex_; pthread_cond_t pcond_; };注意: 若一个class要同时包含MutexLock 和 Condition, 请注意它们的声明顺序和初始化顺序,mutex_ 应该先于 condition_ 构造,并作为后者的参数。