1.Lock
线程互斥锁,使用方法:
Lock g_lock;
..
{
AutoLock scope_lock(g_lock);
}
AutoLock的构造函数和析构函数里会调用Lock的acquire和release
explicit AutoLock(Lock& lock) : lock_(lock) {
lock_.Acquire();
}
~AutoLock() {
lock_.AssertAcquired();
lock_.Release();
}
Lock的acquire和release方法会调用LockImpl的Lock和Unlock方法,LockImpl由各个平台实现
void Acquire() { lock_.Lock(); }
void Release() { lock_.Unlock(); }
internal::LockImpl lock_;
LockImpl在posix上的实现:
LockImpl::LockImpl() {
pthread_mutexattr_t mta;
int rv = pthread_mutexattr_init(&mta);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
......
rv = pthread_mutex_init(&native_handle_, &mta);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
rv = pthread_mutexattr_destroy(&mta);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
}
void LockImpl::Lock() {
int rv = pthread_mutex_lock(&native_handle_);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
}
void LockImpl::Unlock() {
int rv = pthread_mutex_unlock(&native_handle_);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
}
posix上的LockImpl使用pthread_mutex来实现
2. AtomicFlag
多线程安全的一个flag,有两个方法,Set和IsSet。
void Set(); //设置标志
bool IsSet() const; //检查标志是否设置
3.ConditionVariable
接口:
ConditionVariable(Lock* user_lock);
void Wait();
void TimedWait(const TimeDelta& max_time);
// signal all waiting thread
void Broadcast();
// Signal() revives one waiting thread.
void Signal();
wait:
Lock lock;
ConditionVariable cv(&lock);
lock.Acquire();
cv.Wait(); //wait退出后会自动获取锁
signal
//signal之前,获取锁
lock.Acquire()
cv.Signal()
4.Spin wait
用法:
SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(express);
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(delta, expression)
宏,通过while循环等待,直到expression为真,或者1s(delta)超时
5. WaitableEvent
WaitableEvent(ResetPolicy reset_policy, InitialState initial_state);
// Put the event in the un-signaled state.
void Reset();
// Put the event in the signaled state. Causing any thread blocked on Wait
// to be woken up.
void Signal();
// Returns true if the event is in the signaled state, else false. If this
// is not a manual reset event, then this test will cause a reset.
bool IsSignaled();
// Wait indefinitely for the event to be signaled. Wait's return "happens
// after" |Signal| has completed.
void Wait();
// Wait up until wait_delta has passed for the event to be signaled. Returns
// true if the event was signaled.
//
// TimedWait can synchronise its own destruction like |Wait|.
bool TimedWait(const TimeDelta& wait_delta);
// Wait up until end_time deadline has passed for the event to be signaled.
// Return true if the event was signaled.
//
// TimedWaitUntil can synchronise its own destruction like |Wait|.
bool TimedWaitUntil(const TimeTicks& end_time);
WaitableEvent使用WaitableEventKernel来实现。
struct WaitableEventKernel :
public RefCountedThreadSafe {
public:
WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state);
bool Dequeue(Waiter* waiter, void* tag);
base::Lock lock_;
const bool manual_reset_;
bool signaled_;
std::list waiters_;
private:
friend class RefCountedThreadSafe;
~WaitableEventKernel();
};
WaitableEvent在posix平台上的实现
void WaitableEvent::Wait() {
bool result = TimedWaitUntil(TimeTicks::Max());
DCHECK(result) << "TimedWait() should never fail with infinite timeout";
}
bool WaitableEvent::TimedWait(const TimeDelta& wait_delta) {
// TimeTicks takes care of overflow including the cases when wait_delta
// is a maximum value.
return TimedWaitUntil(TimeTicks::Now() + wait_delta);
}
bool WaitableEvent::TimedWaitUntil(const TimeTicks& end_time) {
const bool finite_time = !end_time.is_max();
kernel_->lock_.Acquire();
if (kernel_->signaled_) {
if (!kernel_->manual_reset_) {
// In this case we were signaled when we had no waiters. Now that
// someone has waited upon us, we can automatically reset.
kernel_->signaled_ = false;
}
kernel_->lock_.Release();
return true;
}
SyncWaiter sw;
sw.lock()->Acquire();
Enqueue(&sw);
kernel_->lock_.Release();
// We are violating locking order here by holding the SyncWaiter lock but not
// the WaitableEvent lock. However, this is safe because we don't lock @lock_
// again before unlocking it.
for (;;) {
const TimeTicks current_time(TimeTicks::Now());
if (sw.fired() || (finite_time && current_time >= end_time)) {
const bool return_value = sw.fired();
// We can't acquire @lock_ before releasing the SyncWaiter lock (because
// of locking order), however, in between the two a signal could be fired
// and @sw would accept it, however we will still return false, so the
// signal would be lost on an auto-reset WaitableEvent. Thus we call
// Disable which makes sw::Fire return false.
sw.Disable();
sw.lock()->Release();
// This is a bug that has been enshrined in the interface of
// WaitableEvent now: |Dequeue| is called even when |sw.fired()| is true,
// even though it'll always return false in that case. However, taking
// the lock ensures that |Signal| has completed before we return and
// means that a WaitableEvent can synchronise its own destruction.
kernel_->lock_.Acquire();
kernel_->Dequeue(&sw, &sw);
kernel_->lock_.Release();
return return_value;
}
if (finite_time) {
const TimeDelta max_wait(end_time - current_time);
sw.cv()->TimedWait(max_wait);
} else {
sw.cv()->Wait();
}
}
}
各种版本的Wait都调用到了TimedWaitUntil,在TimedWaitUntil里,先判断是否signal了,如果signal了,则返回true。
如果需要wait,则创建一个SyncWaiter,加入到kernel的waiter列表里。
void WaitableEvent::Reset() {
base::AutoLock locked(kernel_->lock_);
kernel_->signaled_ = false;
}
void WaitableEvent::Signal() {
base::AutoLock locked(kernel_->lock_);
if (kernel_->signaled_)
return;
if (kernel_->manual_reset_) {
SignalAll();
kernel_->signaled_ = true;
} else {
// In the case of auto reset, if no waiters were woken, we remain
// signaled.
if (!SignalOne())
kernel_->signaled_ = true;
}
}
bool WaitableEvent::IsSignaled() {
base::AutoLock locked(kernel_->lock_);
const bool result = kernel_->signaled_;
if (result && !kernel_->manual_reset_)
kernel_->signaled_ = false;
return result;
}
当signal的时候,如果reset的模式是manual的,那么SignalAll,同时将kernel_->signaled_置为true,如果reset模式是Auto,则SignalOne,如果SingalOne返回True,则将kernel_->signaled_置为true。
bool WaitableEvent::SignalAll() {
bool signaled_at_least_one = false;
for (std::list::iterator
i = kernel_->waiters_.begin(); i != kernel_->waiters_.end(); ++i) {
if ((*i)->Fire(this))
signaled_at_least_one = true;
}
kernel_->waiters_.clear();
return signaled_at_least_one;
}
bool WaitableEvent::SignalOne() {
for (;;) {
if (kernel_->waiters_.empty())
return false;
const bool r = (*kernel_->waiters_.begin())->Fire(this);
kernel_->waiters_.pop_front();
if (r)
return true;
}
}