#ifndef SRC_NODE_MUTEX_H_ #define SRC_NODE_MUTEX_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "util.h" #include "uv.h" namespace node { template class ConditionVariableBase; template class MutexBase; struct LibuvMutexTraits; using ConditionVariable = ConditionVariableBase; using Mutex = MutexBase; template 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 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 friend class ConditionVariableBase; mutable typename Traits::MutexT mutex_; DISALLOW_COPY_AND_ASSIGN(MutexBase); }; template class ConditionVariableBase { public: using ScopedLock = typename MutexBase::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 ConditionVariableBase::ConditionVariableBase() { CHECK_EQ(0, Traits::cond_init(&cond_)); } template ConditionVariableBase::~ConditionVariableBase() { Traits::cond_destroy(&cond_); } template void ConditionVariableBase::Broadcast(const ScopedLock&) { Traits::cond_broadcast(&cond_); } template void ConditionVariableBase::Signal(const ScopedLock&) { Traits::cond_signal(&cond_); } template void ConditionVariableBase::Wait(const ScopedLock& scoped_lock) { Traits::cond_wait(&cond_, &scoped_lock.mutex_.mutex_); } template MutexBase::MutexBase() { CHECK_EQ(0, Traits::mutex_init(&mutex_)); } template MutexBase::~MutexBase() { Traits::mutex_destroy(&mutex_); } template void MutexBase::Lock() { Traits::mutex_lock(&mutex_); } template void MutexBase::Unlock() { Traits::mutex_unlock(&mutex_); } template MutexBase::ScopedLock::ScopedLock(const MutexBase& mutex) : mutex_(mutex) { Traits::mutex_lock(&mutex_.mutex_); } template MutexBase::ScopedLock::ScopedLock(const ScopedUnlock& scoped_unlock) : MutexBase(scoped_unlock.mutex_) {} template MutexBase::ScopedLock::~ScopedLock() { Traits::mutex_unlock(&mutex_.mutex_); } template MutexBase::ScopedUnlock::ScopedUnlock(const ScopedLock& scoped_lock) : mutex_(scoped_lock.mutex_) { Traits::mutex_unlock(&mutex_.mutex_); } template MutexBase::ScopedUnlock::~ScopedUnlock() { Traits::mutex_lock(&mutex_.mutex_); } } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_MUTEX_H_