You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

187 lines
4.3 KiB

#ifndef SRC_NODE_MUTEX_H_
#define SRC_NODE_MUTEX_H_
#include "util.h"
#include "uv.h"
namespace node {
template <typename Traits> class ConditionVariableBase;
template <typename Traits> class MutexBase;
struct LibuvMutexTraits;
using ConditionVariable = ConditionVariableBase<LibuvMutexTraits>;
using Mutex = MutexBase<LibuvMutexTraits>;
template <typename Traits>
class MutexBase {
public:
inline MutexBase();
inline ~MutexBase();
inline void Lock();
inline void Unlock();
class ScopedLock;
class ScopedUnlock;
class ScopedLock {
public:
inline explicit ScopedLock(const MutexBase& mutex);
inline explicit ScopedLock(const ScopedUnlock& scoped_unlock);
inline ~ScopedLock();
private:
template <typename> friend class ConditionVariableBase;
friend class ScopedUnlock;
const MutexBase& mutex_;
DISALLOW_COPY_AND_ASSIGN(ScopedLock);
};
class ScopedUnlock {
public:
inline explicit ScopedUnlock(const ScopedLock& scoped_lock);
inline ~ScopedUnlock();
private:
friend class ScopedLock;
const MutexBase& mutex_;
DISALLOW_COPY_AND_ASSIGN(ScopedUnlock);
};
private:
template <typename> friend class ConditionVariableBase;
mutable typename Traits::MutexT mutex_;
DISALLOW_COPY_AND_ASSIGN(MutexBase);
};
template <typename Traits>
class ConditionVariableBase {
public:
using ScopedLock = typename MutexBase<Traits>::ScopedLock;
inline ConditionVariableBase();
inline ~ConditionVariableBase();
inline void Broadcast(const ScopedLock&);
inline void Signal(const ScopedLock&);
inline void Wait(const ScopedLock& scoped_lock);
private:
typename Traits::CondT cond_;
DISALLOW_COPY_AND_ASSIGN(ConditionVariableBase);
};
struct LibuvMutexTraits {
using CondT = uv_cond_t;
using MutexT = uv_mutex_t;
static inline int cond_init(CondT* cond) {
return uv_cond_init(cond);
}
static inline int mutex_init(MutexT* mutex) {
return uv_mutex_init(mutex);
}
static inline void cond_broadcast(CondT* cond) {
uv_cond_broadcast(cond);
}
static inline void cond_destroy(CondT* cond) {
uv_cond_destroy(cond);
}
static inline void cond_signal(CondT* cond) {
uv_cond_signal(cond);
}
static inline void cond_wait(CondT* cond, MutexT* mutex) {
uv_cond_wait(cond, mutex);
}
static inline void mutex_destroy(MutexT* mutex) {
uv_mutex_destroy(mutex);
}
static inline void mutex_lock(MutexT* mutex) {
uv_mutex_lock(mutex);
}
static inline void mutex_unlock(MutexT* mutex) {
uv_mutex_unlock(mutex);
}
};
template <typename Traits>
ConditionVariableBase<Traits>::ConditionVariableBase() {
CHECK_EQ(0, Traits::cond_init(&cond_));
}
template <typename Traits>
ConditionVariableBase<Traits>::~ConditionVariableBase() {
Traits::cond_destroy(&cond_);
}
template <typename Traits>
void ConditionVariableBase<Traits>::Broadcast(const ScopedLock&) {
Traits::cond_broadcast(&cond_);
}
template <typename Traits>
void ConditionVariableBase<Traits>::Signal(const ScopedLock&) {
Traits::cond_signal(&cond_);
}
template <typename Traits>
void ConditionVariableBase<Traits>::Wait(const ScopedLock& scoped_lock) {
Traits::cond_wait(&cond_, &scoped_lock.mutex_.mutex_);
}
template <typename Traits>
MutexBase<Traits>::MutexBase() {
CHECK_EQ(0, Traits::mutex_init(&mutex_));
}
template <typename Traits>
MutexBase<Traits>::~MutexBase() {
Traits::mutex_destroy(&mutex_);
}
template <typename Traits>
void MutexBase<Traits>::Lock() {
Traits::mutex_lock(&mutex_);
}
template <typename Traits>
void MutexBase<Traits>::Unlock() {
Traits::mutex_unlock(&mutex_);
}
template <typename Traits>
MutexBase<Traits>::ScopedLock::ScopedLock(const MutexBase& mutex)
: mutex_(mutex) {
Traits::mutex_lock(&mutex_.mutex_);
}
template <typename Traits>
MutexBase<Traits>::ScopedLock::ScopedLock(const ScopedUnlock& scoped_unlock)
: MutexBase(scoped_unlock.mutex_) {}
template <typename Traits>
MutexBase<Traits>::ScopedLock::~ScopedLock() {
Traits::mutex_unlock(&mutex_.mutex_);
}
template <typename Traits>
MutexBase<Traits>::ScopedUnlock::ScopedUnlock(const ScopedLock& scoped_lock)
: mutex_(scoped_lock.mutex_) {
Traits::mutex_unlock(&mutex_.mutex_);
}
template <typename Traits>
MutexBase<Traits>::ScopedUnlock::~ScopedUnlock() {
Traits::mutex_lock(&mutex_.mutex_);
}
} // namespace node
#endif // SRC_NODE_MUTEX_H_