namespace muduo
{
// Use as data member of a class, eg.
//
// class Foo
// {
// public:
// int size() const;
//
// private:
// mutable MutexLock mutex_;//mutex_作为类成员,来保护类中的数据.声明为mutable,则mutex_始终可变,即使是在const函数中
// std::vector<int> data_; // GUARDED BY mutex_
// };
class MutexLock : boost::noncopyable
{
public:
MutexLock()
: holder_(0)
{
MCHECK(pthread_mutex_init(&mutex_, NULL));
}
~MutexLock()
{
assert(holder_ == 0);
MCHECK(pthread_mutex_destroy(&mutex_));
}
// internal usage
void lock()
{
MCHECK(pthread_mutex_lock(&mutex_));
assignHolder();
}
void unlock()
{
unassignHolder();
MCHECK(pthread_mutex_unlock(&mutex_));
}
pthread_mutex_t* getPthreadMutex() /* non-const */
{
return &mutex_;
}
private:
void unassignHolder()
{
holder_ = 0;
}
void assignHolder()
{
holder_ = CurrentThread::tid();//记录锁持有者的tid
}
pthread_mutex_t mutex_;//互斥锁
pid_t holder_;//用于记录互斥锁的当前持有线程的tid,当holder_为0时,表示锁未被任何线程持有,此时可以销毁
};
// Use as a stack variable, eg. //作为一个栈变量被使用(不用new来分配),这样当离开生存区间时,变量会被自动销毁
// int Foo::size() const
// {
// MutexLockGuard lock(mutex_);
// return data_.size();
// }
class MutexLockGuard : boost::noncopyable
{
public:
explicit MutexLockGuard(MutexLock& mutex)
: mutex_(mutex)
{
mutex_.lock();//在构造时调用互斥锁的lock方法持有锁,并记录当前线程tid:调用pthread_mutex_lock()和assignHolder()
}
~MutexLockGuard()
{
mutex_.unlock();//在析构时释放锁
}
private:
MutexLock& mutex_;
};
}
// Prevent misuse like:
// MutexLockGuard(mutex_);
// A tempory object doesn't hold the lock for long!
#define MutexLockGuard(x) error "Missing guard object name"
#endif // MUDUO_BASE_MUTEX_H
用法示例如下:
class Foo
// {
// public:
// int size() const;
//
// private:
// mutable MutexLock mutex_;//mutex_作为类成员,来保护类中的数据.声明为mutable,则mutex_始终可变,即使是在const函数中
// std::vector<int> data_; // GUARDED BY mutex_
// };
然后在每次需要进入临界区的时候都先初始化一个MutexLockGuard对象
MutexLockGuard lock(mutex_); //在构造lock中就会调用mutex的lock()方法持有锁