mutex 配合 线程id
class CAPABILITY("mutex") MutexLock : noncopyable
{
public:
MutexLock()
: holder_(0)
{
MCHECK(pthread_mutex_init(&mutex_, NULL));
}
// 只有未上锁的状态可以析构
~MutexLock()
{
assert(holder_ == 0);
MCHECK(pthread_mutex_destroy(&mutex_));
}
// must be called when locked, i.e. for assertion
// 是否当前线程 锁
bool isLockedByThisThread() const
{
return holder_ == CurrentThread::tid();
}
// 断言 一定是当前线程上锁该 mutex
void assertLocked() const ASSERT_CAPABILITY(this)
{
assert(isLockedByThisThread());
}
// internal usage
void lock() ACQUIRE()
{
// mutex 上锁后,给mutex赋值当前线程的tid
MCHECK(pthread_mutex_lock(&mutex_));
assignHolder();
}
void unlock() RELEASE()
{
// 释放锁之前 重置 holder
unassignHolder();
MCHECK(pthread_mutex_unlock(&mutex_));
}
// 获得
pthread_mutex_t* getPthreadMutex() /* non-const */
{
return &mutex_;
}
private:
friend class Condition;
// 类中类,守护未被分配; 创建 UnassignGuard 传入 MutexLock 构造后,将 holder清除
class UnassignGuard : noncopyable
{
public:
// 引用,必须非nullptr
explicit UnassignGuard(MutexLock& owner)
: owner_(owner)
{
owner_.unassignHolder();
}
~UnassignGuard()
{
owner_.assignHolder();
}
private:
MutexLock& owner_;
};
void unassignHolder()
{
holder_ = 0;
}
void assignHolder()
{
// 赋值,使用线程id
holder_ = CurrentThread::tid();
}
// 锁和线程id 的组合,可以更加清晰的在多线程环境中使用mutex
pthread_mutex_t mutex_;
pid_t holder_;
};
锁和线程id 的组合,可以更加清晰的在多线程环境中使用mutex
Condition
// condition 的使用 必须结合 mutex
class Condition : noncopyable
{
public:
explicit Condition(MutexLock& mutex)
: mutex_(mutex)
{
MCHECK(pthread_cond_init(&pcond_, NULL));
}
~Condition()
{
MCHECK(pthread_cond_destroy(&pcond_));
}
void wait()
{
// 资源控制类,构造时 清空当前 holder,析构函数中设置holder为当前线程id
MutexLock::UnassignGuard ug(mutex_);
MCHECK(pthread_cond_wait(&pcond_, mutex_.getPthreadMutex()));
}
// returns true if time out, false otherwise.
bool waitForSeconds(double seconds);
void notify()
{
MCHECK(pthread_cond_signal(&pcond_));
}
void notifyAll()
{
MCHECK(pthread_cond_broadcast(&pcond_));
}
private:
MutexLock& mutex_;
pthread_cond_t pcond_;
};
Condition 类中有 MutexLock 的引用,所以构造过程中,必须要传入一个mutex实例。
wait函数中使用 资源封装类MutexLock::UnassignGuard,确保在condition等待结束后获得mutex上锁时,设置当前线程id为mutex的holder。