Marine Library  1.0
C++ library for Linux Networking Development
mutex.hh
1 #ifndef DOZERG_MUTEX_H_20070924
2 #define DOZERG_MUTEX_H_20070924
3 
4 /*
5  对POSIX锁机制进行简单的封装
6  方便使用,隐藏底层实现
7  CMutexAttr 互斥锁的属性 CMutex 互斥锁 CCondAttr 条件变量的属性 CCondition 条件变量 CRWLockAttr 读写锁的属性 CRWLock 读写锁 CSpinLock 自旋锁 CFileLock 文件锁 CLockAdapter 锁适配器 CGuard 锁守卫 COnceGuard 确保某些函数只运行一次 CThreadData 线程本地数据 CBarrierAttr 栅栏的属性 CBarrier 栅栏,用于多线程对齐执行点 //*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
8  CMutex 互斥锁 CCondAttr 条件变量的属性 CCondition 条件变量 CRWLockAttr 读写锁的属性 CRWLock 读写锁 CSpinLock 自旋锁 CFileLock 文件锁 CLockAdapter 锁适配器 CGuard 锁守卫 COnceGuard 确保某些函数只运行一次 CThreadData 线程本地数据 CBarrierAttr 栅栏的属性 CBarrier 栅栏,用于多线程对齐执行点 //*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
9  CCondAttr 条件变量的属性 CCondition 条件变量 CRWLockAttr 读写锁的属性 CRWLock 读写锁 CSpinLock 自旋锁 CFileLock 文件锁 CLockAdapter 锁适配器 CGuard 锁守卫 COnceGuard 确保某些函数只运行一次 CThreadData 线程本地数据 CBarrierAttr 栅栏的属性 CBarrier 栅栏,用于多线程对齐执行点 //*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
10  CCondition 条件变量
11  CRWLockAttr 读写锁的属性 CRWLock 读写锁 CSpinLock 自旋锁 CFileLock 文件锁 CLockAdapter 锁适配器 CGuard 锁守卫 COnceGuard 确保某些函数只运行一次 CThreadData 线程本地数据 CBarrierAttr 栅栏的属性 CBarrier 栅栏,用于多线程对齐执行点 //*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
12  CRWLock 读写锁
13  CSpinLock 自旋锁
14  CFileLock 文件锁
15  CLockAdapter 锁适配器
16  CGuard 锁守卫
17  COnceGuard 确保某些函数只运行一次 CThreadData 线程本地数据 CBarrierAttr 栅栏的属性 CBarrier 栅栏,用于多线程对齐执行点 //*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
18  CThreadData 线程本地数据 CBarrierAttr 栅栏的属性 CBarrier 栅栏,用于多线程对齐执行点 //*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
19  CBarrierAttr 栅栏的属性 CBarrier 栅栏,用于多线程对齐执行点 //*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
20  CBarrier 栅栏,用于多线程对齐执行点//*/ #include <sys/file.h> //flock #include <pthread.h> #include <stdexcept> //std::runtime_error #include "scoped_ptr.hh" #include "file.hh" #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs #include "tools/system.hh" //ErrorMsg NS_SERVER_BEGIN class CMutex; class CMutexAttr { friend class CMutex; typedef CMutexAttr __Myt; public: CMutexAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_)); } ~CMutexAttr(){ ::pthread_mutexattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } void type(int t) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t)); } int type() const throw(std::runtime_error){ int t = 0; THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t)); return t; } private: const pthread_mutexattr_t * a() const{return &attr_;} CMutexAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_mutexattr_t attr_; }; class CCondition; //lock types class CMutex { friend class CCondition; typedef CMutex __Myt; public: CMutex() throw(std::runtime_error){ #ifdef NDEBUG THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL)); #else //check dead lock CMutexAttr attr; attr.type(PTHREAD_MUTEX_ERRORCHECK); THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); #endif } explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a())); } virtual ~CMutex(){ ::pthread_mutex_destroy(&mutex_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_lock(m())); } bool tryLock() volatile{ return (0 == ::pthread_mutex_trylock(m())); } //在指定的timeMs毫秒内如果不能lock,返回false bool timeLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_mutex_timedlock(m(), &ts)); } void unlock() volatile const throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_mutex_unlock(m())); } private: pthread_mutex_t * m() const volatile{ return const_cast<pthread_mutex_t *>(&mutex_); } CMutex(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_mutex_t mutex_; }; class CCondAttr { friend class CCondition; typedef CCondAttr __Myt; public: CCondAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_)); } ~CCondAttr(){ ::pthread_condattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_condattr_t * a() const{return &attr_;} CCondAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_condattr_t attr_; }; class CCondition { typedef CCondition __Myt; public: CCondition() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL)); } explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a())); } ~CCondition(){ ::pthread_cond_destroy(&cond_); } void signal() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_)); } void broadcast() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_)); } void wait(volatile CMutex & m) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m())); } //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
21 //*/
22 
23 #include <sys/file.h> //flock
24 #include <pthread.h>
25 #include <stdexcept> //std::runtime_error
26 #include "scoped_ptr.hh"
27 #include "file.hh"
28 #include "tools/time.hh" //GetAbsTimespec, MonoTimeUs
29 #include "tools/system.hh" //ErrorMsg
30 
31 NS_SERVER_BEGIN
32 
33 class CMutex;
34 
36 {
37  friend class CMutex;
38  typedef CMutexAttr __Myt;
39 public:
40  CMutexAttr() throw(std::runtime_error){
41  THROW_RT_IF_FAIL(::pthread_mutexattr_init(&attr_));
42  }
43  ~CMutexAttr(){
44  ::pthread_mutexattr_destroy(&attr_);
45  }
46  void pshared(bool on) throw(std::runtime_error){
47  THROW_RT_IF_FAIL(::pthread_mutexattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE)));
48  }
49  bool pshared() const throw(std::runtime_error){
50  int on = 0;
51  THROW_RT_IF_FAIL(::pthread_mutexattr_getpshared(&attr_, &on));
52  return (PTHREAD_PROCESS_SHARED == on);
53  }
54  void type(int t) throw(std::runtime_error){
55  THROW_RT_IF_FAIL(::pthread_mutexattr_settype(&attr_, t));
56  }
57  int type() const throw(std::runtime_error){
58  int t = 0;
59  THROW_RT_IF_FAIL(::pthread_mutexattr_gettype(&attr_, &t));
60  return t;
61  }
62 private:
63  const pthread_mutexattr_t * a() const{return &attr_;}
64  CMutexAttr(const __Myt &); //disable copy and assignment
65  __Myt & operator =(const __Myt &);
66  //field
67  pthread_mutexattr_t attr_;
68 };
69 
70 class CCondition;
71 
72 //lock types
73 class CMutex
74 {
75  friend class CCondition;
76  typedef CMutex __Myt;
77 public:
78  CMutex() throw(std::runtime_error){
79 #ifdef NDEBUG
80  THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, NULL));
81 #else //check dead lock
82  CMutexAttr attr;
83  attr.type(PTHREAD_MUTEX_ERRORCHECK);
84  THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a()));
85 #endif
86  }
87  explicit CMutex(const CMutexAttr & attr) throw(std::runtime_error){
88  THROW_RT_IF_FAIL(::pthread_mutex_init(&mutex_, attr.a()));
89  }
90  virtual ~CMutex(){
91  ::pthread_mutex_destroy(&mutex_);
92  }
93  void lock() volatile throw(std::runtime_error){
94  THROW_RT_IF_FAIL(::pthread_mutex_lock(m()));
95  }
96  bool tryLock() volatile{
97  return (0 == ::pthread_mutex_trylock(m()));
98  }
99  //在指定的timeMs毫秒内如果不能lock,返回false
100  bool timeLock(uint32_t timeMs) volatile{
101  timespec ts;
102  if(!tools::GetAbsTimespec(timeMs, &ts))
103  return false;
104  return (0 == ::pthread_mutex_timedlock(m(), &ts));
105  }
106  void unlock() volatile const throw(std::runtime_error){
107  THROW_RT_IF_FAIL(::pthread_mutex_unlock(m()));
108  }
109 private:
110  pthread_mutex_t * m() const volatile{
111  return const_cast<pthread_mutex_t *>(&mutex_);
112  }
113  CMutex(const __Myt &); //disable copy and assignment
114  __Myt & operator =(const __Myt &);
115  //field
116  mutable pthread_mutex_t mutex_;
117 };
118 
120 {
121  friend class CCondition;
122  typedef CCondAttr __Myt;
123 public:
124  CCondAttr() throw(std::runtime_error){
125  THROW_RT_IF_FAIL(::pthread_condattr_init(&attr_));
126  }
127  ~CCondAttr(){
128  ::pthread_condattr_destroy(&attr_);
129  }
130  void pshared(bool on) throw(std::runtime_error){
131  THROW_RT_IF_FAIL(::pthread_condattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE)));
132  }
133  bool pshared() const throw(std::runtime_error){
134  int on = 0;
135  THROW_RT_IF_FAIL(::pthread_condattr_getpshared(&attr_, &on));
136  return (PTHREAD_PROCESS_SHARED == on);
137  }
138 private:
139  const pthread_condattr_t * a() const{return &attr_;}
140  CCondAttr(const __Myt &); //disable copy and assignment
141  __Myt operator =(const __Myt &);
142  //field
143  pthread_condattr_t attr_;
144 };
145 
147 {
148  typedef CCondition __Myt;
149 public:
150  CCondition() throw(std::runtime_error){
151  THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, NULL));
152  }
153  explicit CCondition(const CCondAttr & attr) throw(std::runtime_error){
154  THROW_RT_IF_FAIL(::pthread_cond_init(&cond_, attr.a()));
155  }
156  ~CCondition(){
157  ::pthread_cond_destroy(&cond_);
158  }
159  void signal() throw(std::runtime_error){
160  THROW_RT_IF_FAIL(::pthread_cond_signal(&cond_));
161  }
162  void broadcast() throw(std::runtime_error){
163  THROW_RT_IF_FAIL(::pthread_cond_broadcast(&cond_));
164  }
165  void wait(volatile CMutex & m) throw(std::runtime_error){
166  THROW_RT_IF_FAIL(::pthread_cond_wait(&cond_, m.m()));
167  }
168  //等待指定的timeMs毫秒 bool timeWait(volatile CMutex & m, uint32_t timeMs){ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts)); } private: CCondition(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_cond_t cond_; }; class CRWLock; class CRWLockAttr { friend class CRWLock; typedef CRWLockAttr __Myt; public: CRWLockAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_)); } ~CRWLockAttr(){ ::pthread_rwlockattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_rwlockattr_t * a() const{return &attr_;} CRWLockAttr(const __Myt &); //disable copy and assignment __Myt operator =(const __Myt &); //field pthread_rwlockattr_t attr_; }; class CRWLock { typedef CRWLock __Myt; public: CRWLock() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL)); } explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a())); } ~CRWLock(){ ::pthread_rwlock_destroy(&lock_); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l())); } bool tryReadLock() const volatile{ return (0 == ::pthread_rwlock_tryrdlock(l())); } //在指定的timeMs毫秒内如果不能rdlock,返回false bool timeReadLock(uint32_t timeMs) const volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedrdlock(l(), &ts)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l())); } bool tryWriteLock() volatile{ return (0 == ::pthread_rwlock_trywrlock(l())); } //在指定的timeMs毫秒内如果不能wrlock,返回false bool timeWriteLock(uint32_t timeMs) volatile{ timespec ts; if(!tools::GetAbsTimespec(timeMs, &ts)) return false; return (0 == ::pthread_rwlock_timedwrlock(l(), &ts)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l())); } private: pthread_rwlock_t * l() const volatile{ return const_cast<pthread_rwlock_t *>(&lock_); } CRWLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_rwlock_t lock_; }; class CSpinLock { typedef CSpinLock __Myt; public: explicit CSpinLock(int pshared = false) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } ~CSpinLock(){ ::pthread_spin_destroy(&lock_); } void lock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_lock(l())); } bool tryLock() volatile{ return (0 == ::pthread_spin_trylock(l())); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_spin_unlock(l())); } private: pthread_spinlock_t * l() const volatile{ return const_cast<pthread_spinlock_t *>(&lock_); } CSpinLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field mutable pthread_spinlock_t lock_; }; class CFileLock { typedef CFileLock __Myt; public: explicit CFileLock(const char * filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } explicit CFileLock(const std::string & filename) : file_(filename) { THROW_RT_IF_FAIL(file_.valid() ? 0 : errno); } void readLock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno); } bool tryReadLock() const volatile{ return (0 == ::flock(fd(), LOCK_SH | LOCK_NB)); } void writeLock() volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno); } bool tryWriteLock() volatile{ return (0 == ::flock(fd(), LOCK_EX | LOCK_NB)); } void unlock() const volatile throw(std::runtime_error){ THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno); } private: int fd() const volatile{ return const_cast<const CFile &>(file_).fd(); } CFileLock(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //filed CFile file_; }; //adapters for lock types template<class T>struct CLockAdapter{}; template<> struct CLockAdapter<CMutex> { typedef CMutex lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{ const_cast<volatile lock_type &>(m).lock(); } bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return const_cast<volatile lock_type &>(m).timeLock(timeMs); } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeLock(timeMs); } }; template<> struct CLockAdapter<CRWLock> { typedef CRWLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ return m.timeReadLock(timeMs); } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ return m.timeWriteLock(timeMs); } }; template<> struct CLockAdapter<CSpinLock> { typedef CSpinLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();} bool tryReadLock(const volatile lock_type & m) const{ return const_cast<volatile lock_type &>(m).tryLock(); } bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.lock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; template<> struct CLockAdapter<CFileLock> { typedef CFileLock lock_type; void unlock(const volatile lock_type & m) const{m.unlock();} void readLock(const volatile lock_type & m) const{m.readLock();} bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();} bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryReadLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } void writeLock(volatile lock_type & m) const{m.writeLock();} bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();} bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{ const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000; do{ if(tryWriteLock(m)) return true; }while(end > tools::MonoTimeUs(NULL, true)); return false; } }; //guard for all lock types template<class LockT> class CGuard { //typedefs typedef CGuard __Myt; public: typedef typename COmitCV<LockT>::result_type lock_type; typedef CLockAdapter<lock_type> adapter_type; //functions explicit CGuard(volatile lock_type & r, bool bWrite = true) : lock_(&r) { bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r); } explicit CGuard(const volatile lock_type & r) : lock_(&r) { adapter_type().readLock(r); } explicit CGuard(volatile lock_type * p, bool bWrite = true) : lock_(p) { if(lock_) bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p); } explicit CGuard(const volatile lock_type * p) : lock_(p) { adapter_type().readLock(*p); } ~CGuard(){ if(lock_) adapter_type().unlock(*lock_); } private: CGuard(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field const volatile lock_type * const lock_; }; /* template<class T, class LockT> class CGuardObj : public CGuard<LockT> { typedef CGuardObj<T, LockT> __Myt; typedef CGuard<LockT> guard_type; public: typedef typename guard_type::lock_type lock_type; typedef typename COmitCV<T>::result_type value_type; typedef value_type & reference; typedef const value_type & const_reference; CGuardObj(reference obj, volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type & r) : g_(r) , obj_(obj) {} CGuardObj(reference obj, volatile lock_type * p) : g_(p) , obj_(obj) {} CGuardObj(const_reference obj, const volatile lock_type * p) : g_(p) , obj_(obj) {} T & obj() const{return obj_;} private: guard_type g_; T & obj_; }; template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock) { return CGuardObj<T, LockT>(obj, lock); } template<class T, class LockT> inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock) { return CGuardObj<T, LockT>(obj, lock); } */ struct COnceGuard { typedef void (*__Function)(void); explicit COnceGuard(__Function func = NULL) : func_(func) , once_(PTHREAD_ONCE_INIT) {} void runOnce(__Function func = NULL){ ::pthread_once(&once_, (func ? func : func_)); } private: __Function func_; pthread_once_t once_; }; template<class T> class CThreadData { typedef CThreadData<T> __Myt; public: typedef T value_type; typedef value_type & reference; typedef const value_type & const_reference; typedef value_type * pointer; typedef const value_type * const_pointer; private: typedef CScopedPtr<value_type> __Ptr; static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));} public: CThreadData() : key_(PTHREAD_KEYS_MAX) { ::pthread_key_create(&key_, &Dtor); } bool valid() const{return (key_ != PTHREAD_KEYS_MAX);} pointer ptr(){return static_cast<pointer>(getValue());} const_pointer ptr() const{return static_cast<const_pointer>(getValue());} reference ref(){return *ptr();} const_reference ref() const{return *ptr();} std::string toString() const{ CToString oss; oss<<"{key_="<<key_<<'}'; return oss.str(); } private: void * getValue() const{ if(!valid()) return NULL; void * p = ::pthread_getspecific(key_); if(NULL == p){ __Ptr sp(tools::New<value_type>()); if(0 == ::pthread_setspecific(key_, sp.get())) p = sp.release(); } return p; } //field pthread_key_t key_; }; class CBarrier; class CBarrierAttr { friend class CBarrier; typedef CBarrierAttr __Myt; public: CBarrierAttr() throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_)); } ~CBarrierAttr(){ ::pthread_barrierattr_destroy(&attr_); } void pshared(bool on) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE))); } bool pshared() const throw(std::runtime_error){ int on = 0; THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on)); return (PTHREAD_PROCESS_SHARED == on); } private: const pthread_barrierattr_t * a() const{return &attr_;} CBarrierAttr(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); pthread_barrierattr_t attr_; }; class CBarrier { typedef CBarrier __Myt; public: explicit CBarrier(size_t count) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count)); } CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){ THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count)); } ~CBarrier(){ ::pthread_barrier_destroy(&barrier_); } void wait() throw(std::runtime_error){ int err = ::pthread_barrier_wait(&barrier_); if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err) throw std::runtime_error(tools::ErrorMsg(err).c_str()); } private: CBarrier(const __Myt &); //disable copy and assignment __Myt & operator =(const __Myt &); //field pthread_barrier_t barrier_; }; NS_SERVER_END #endif
169  bool timeWait(volatile CMutex & m, uint32_t timeMs){
170  timespec ts;
171  if(!tools::GetAbsTimespec(timeMs, &ts))
172  return false;
173  return (0 == ::pthread_cond_timedwait(&cond_, m.m(), &ts));
174  }
175 private:
176  CCondition(const __Myt &); //disable copy and assignment
177  __Myt & operator =(const __Myt &);
178  //field
179  pthread_cond_t cond_;
180 };
181 
182 class CRWLock;
183 
185 {
186  friend class CRWLock;
187  typedef CRWLockAttr __Myt;
188 public:
189  CRWLockAttr() throw(std::runtime_error){
190  THROW_RT_IF_FAIL(::pthread_rwlockattr_init(&attr_));
191  }
192  ~CRWLockAttr(){
193  ::pthread_rwlockattr_destroy(&attr_);
194  }
195  void pshared(bool on) throw(std::runtime_error){
196  THROW_RT_IF_FAIL(::pthread_rwlockattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE)));
197  }
198  bool pshared() const throw(std::runtime_error){
199  int on = 0;
200  THROW_RT_IF_FAIL(::pthread_rwlockattr_getpshared(&attr_, &on));
201  return (PTHREAD_PROCESS_SHARED == on);
202  }
203 private:
204  const pthread_rwlockattr_t * a() const{return &attr_;}
205  CRWLockAttr(const __Myt &); //disable copy and assignment
206  __Myt operator =(const __Myt &);
207  //field
208  pthread_rwlockattr_t attr_;
209 };
210 
211 class CRWLock
212 {
213  typedef CRWLock __Myt;
214 public:
215  CRWLock() throw(std::runtime_error){
216  THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, NULL));
217  }
218  explicit CRWLock(const CRWLockAttr & attr) throw(std::runtime_error){
219  THROW_RT_IF_FAIL(::pthread_rwlock_init(&lock_, attr.a()));
220  }
221  ~CRWLock(){
222  ::pthread_rwlock_destroy(&lock_);
223  }
224  void readLock() const volatile throw(std::runtime_error){
225  THROW_RT_IF_FAIL(::pthread_rwlock_rdlock(l()));
226  }
227  bool tryReadLock() const volatile{
228  return (0 == ::pthread_rwlock_tryrdlock(l()));
229  }
230  //在指定的timeMs毫秒内如果不能rdlock,返回false
231  bool timeReadLock(uint32_t timeMs) const volatile{
232  timespec ts;
233  if(!tools::GetAbsTimespec(timeMs, &ts))
234  return false;
235  return (0 == ::pthread_rwlock_timedrdlock(l(), &ts));
236  }
237  void writeLock() volatile throw(std::runtime_error){
238  THROW_RT_IF_FAIL(::pthread_rwlock_wrlock(l()));
239  }
240  bool tryWriteLock() volatile{
241  return (0 == ::pthread_rwlock_trywrlock(l()));
242  }
243  //在指定的timeMs毫秒内如果不能wrlock,返回false
244  bool timeWriteLock(uint32_t timeMs) volatile{
245  timespec ts;
246  if(!tools::GetAbsTimespec(timeMs, &ts))
247  return false;
248  return (0 == ::pthread_rwlock_timedwrlock(l(), &ts));
249  }
250  void unlock() const volatile throw(std::runtime_error){
251  THROW_RT_IF_FAIL(::pthread_rwlock_unlock(l()));
252  }
253 private:
254  pthread_rwlock_t * l() const volatile{
255  return const_cast<pthread_rwlock_t *>(&lock_);
256  }
257  CRWLock(const __Myt &); //disable copy and assignment
258  __Myt & operator =(const __Myt &);
259  //field
260  mutable pthread_rwlock_t lock_;
261 };
262 
264 {
265  typedef CSpinLock __Myt;
266 public:
267  explicit CSpinLock(int pshared = false) throw(std::runtime_error){
268  THROW_RT_IF_FAIL(::pthread_spin_init(&lock_, (pshared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE)));
269  }
270  ~CSpinLock(){
271  ::pthread_spin_destroy(&lock_);
272  }
273  void lock() volatile throw(std::runtime_error){
274  THROW_RT_IF_FAIL(::pthread_spin_lock(l()));
275  }
276  bool tryLock() volatile{
277  return (0 == ::pthread_spin_trylock(l()));
278  }
279  void unlock() const volatile throw(std::runtime_error){
280  THROW_RT_IF_FAIL(::pthread_spin_unlock(l()));
281  }
282 private:
283  pthread_spinlock_t * l() const volatile{
284  return const_cast<pthread_spinlock_t *>(&lock_);
285  }
286  CSpinLock(const __Myt &); //disable copy and assignment
287  __Myt & operator =(const __Myt &);
288  //field
289  mutable pthread_spinlock_t lock_;
290 };
291 
293 {
294  typedef CFileLock __Myt;
295 public:
296  explicit CFileLock(const char * filename)
297  : file_(filename)
298  {
299  THROW_RT_IF_FAIL(file_.valid() ? 0 : errno);
300  }
301  explicit CFileLock(const std::string & filename)
302  : file_(filename)
303  {
304  THROW_RT_IF_FAIL(file_.valid() ? 0 : errno);
305  }
306  void readLock() const volatile throw(std::runtime_error){
307  THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_SH)) ? 0 : errno);
308  }
309  bool tryReadLock() const volatile{
310  return (0 == ::flock(fd(), LOCK_SH | LOCK_NB));
311  }
312  void writeLock() volatile throw(std::runtime_error){
313  THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_EX)) ? 0 : errno);
314  }
315  bool tryWriteLock() volatile{
316  return (0 == ::flock(fd(), LOCK_EX | LOCK_NB));
317  }
318  void unlock() const volatile throw(std::runtime_error){
319  THROW_RT_IF_FAIL((0 == ::flock(fd(), LOCK_UN)) ? 0 : errno);
320  }
321 private:
322  int fd() const volatile{
323  return const_cast<const CFile &>(file_).fd();
324  }
325  CFileLock(const __Myt &); //disable copy and assignment
326  __Myt & operator =(const __Myt &);
327  //filed
328  CFile file_;
329 };
330 
331 //adapters for lock types
332 template<class T>struct CLockAdapter{};
333 
334 template<>
336 {
337  typedef CMutex lock_type;
338  void unlock(const volatile lock_type & m) const{m.unlock();}
339  void readLock(const volatile lock_type & m) const{
340  const_cast<volatile lock_type &>(m).lock();
341  }
342  bool tryReadLock(const volatile lock_type & m) const{
343  return const_cast<volatile lock_type &>(m).tryLock();
344  }
345  bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{
346  return const_cast<volatile lock_type &>(m).timeLock(timeMs);
347  }
348  void writeLock(volatile lock_type & m) const{m.lock();}
349  bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();}
350  bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{
351  return m.timeLock(timeMs);
352  }
353 };
354 
355 template<>
357 {
358  typedef CRWLock lock_type;
359  void unlock(const volatile lock_type & m) const{m.unlock();}
360  void readLock(const volatile lock_type & m) const{m.readLock();}
361  bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();}
362  bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{
363  return m.timeReadLock(timeMs);
364  }
365  void writeLock(volatile lock_type & m) const{m.writeLock();}
366  bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();}
367  bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{
368  return m.timeWriteLock(timeMs);
369  }
370 };
371 
372 template<>
374 {
375  typedef CSpinLock lock_type;
376  void unlock(const volatile lock_type & m) const{m.unlock();}
377  void readLock(const volatile lock_type & m) const{const_cast<volatile lock_type &>(m).lock();}
378  bool tryReadLock(const volatile lock_type & m) const{
379  return const_cast<volatile lock_type &>(m).tryLock();
380  }
381  bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{
382  const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000;
383  do{
384  if(tryReadLock(m))
385  return true;
386  }while(end > tools::MonoTimeUs(NULL, true));
387  return false;
388  }
389  void writeLock(volatile lock_type & m) const{m.lock();}
390  bool tryWriteLock(volatile lock_type & m) const{return m.tryLock();}
391  bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{
392  const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000;
393  do{
394  if(tryWriteLock(m))
395  return true;
396  }while(end > tools::MonoTimeUs(NULL, true));
397  return false;
398  }
399 };
400 
401 template<>
403 {
404  typedef CFileLock lock_type;
405  void unlock(const volatile lock_type & m) const{m.unlock();}
406  void readLock(const volatile lock_type & m) const{m.readLock();}
407  bool tryReadLock(const volatile lock_type & m) const{return m.tryReadLock();}
408  bool timeReadLock(const volatile lock_type & m, uint32_t timeMs) const{
409  const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000;
410  do{
411  if(tryReadLock(m))
412  return true;
413  }while(end > tools::MonoTimeUs(NULL, true));
414  return false;
415  }
416  void writeLock(volatile lock_type & m) const{m.writeLock();}
417  bool tryWriteLock(volatile lock_type & m) const{return m.tryWriteLock();}
418  bool timeWriteLock(volatile lock_type & m, uint32_t timeMs) const{
419  const int64_t end = tools::MonoTimeUs(NULL, true) + timeMs * 1000;
420  do{
421  if(tryWriteLock(m))
422  return true;
423  }while(end > tools::MonoTimeUs(NULL, true));
424  return false;
425  }
426 };
427 
428 //guard for all lock types
429 template<class LockT>
430 class CGuard
431 {
432  //typedefs
433  typedef CGuard __Myt;
434 public:
435  typedef typename COmitCV<LockT>::result_type lock_type;
437  //functions
438  explicit CGuard(volatile lock_type & r, bool bWrite = true)
439  : lock_(&r)
440  {
441  bWrite ? adapter_type().writeLock(r) : adapter_type().readLock(r);
442  }
443  explicit CGuard(const volatile lock_type & r)
444  : lock_(&r)
445  {
446  adapter_type().readLock(r);
447  }
448  explicit CGuard(volatile lock_type * p, bool bWrite = true)
449  : lock_(p)
450  {
451  if(lock_)
452  bWrite ? adapter_type().writeLock(*p) : adapter_type().readLock(*p);
453  }
454  explicit CGuard(const volatile lock_type * p)
455  : lock_(p)
456  {
457  adapter_type().readLock(*p);
458  }
459  ~CGuard(){
460  if(lock_)
461  adapter_type().unlock(*lock_);
462  }
463 private:
464  CGuard(const __Myt &); //disable copy and assignment
465  __Myt & operator =(const __Myt &);
466  //field
467  const volatile lock_type * const lock_;
468 };
469 
470 /*
471 template<class T, class LockT>
472 class CGuardObj : public CGuard<LockT>
473 {
474  typedef CGuardObj<T, LockT> __Myt;
475  typedef CGuard<LockT> guard_type;
476 public:
477  typedef typename guard_type::lock_type lock_type;
478  typedef typename COmitCV<T>::result_type value_type;
479  typedef value_type & reference;
480  typedef const value_type & const_reference;
481  CGuardObj(reference obj, volatile lock_type & r)
482  : g_(r)
483  , obj_(obj)
484  {}
485  CGuardObj(const_reference obj, const volatile lock_type & r)
486  : g_(r)
487  , obj_(obj)
488  {}
489  CGuardObj(reference obj, volatile lock_type * p)
490  : g_(p)
491  , obj_(obj)
492  {}
493  CGuardObj(const_reference obj, const volatile lock_type * p)
494  : g_(p)
495  , obj_(obj)
496  {}
497  T & obj() const{return obj_;}
498 private:
499  guard_type g_;
500  T & obj_;
501 };
502 
503 template<class T, class LockT>
504 inline CGuardObj<T, LockT> lockObj(T & obj, LockT & lock)
505 {
506  return CGuardObj<T, LockT>(obj, lock);
507 }
508 
509 template<class T, class LockT>
510 inline CGuardObj<T, LockT> lockObj(T & obj, LockT * lock)
511 {
512  return CGuardObj<T, LockT>(obj, lock);
513 }
514 */
515 
517 {
518  typedef void (*__Function)(void);
519  explicit COnceGuard(__Function func = NULL)
520  : func_(func)
521  , once_(PTHREAD_ONCE_INIT)
522  {}
523  void runOnce(__Function func = NULL){
524  ::pthread_once(&once_, (func ? func : func_));
525  }
526 private:
527  __Function func_;
528  pthread_once_t once_;
529 };
530 
531 template<class T>
533 {
534  typedef CThreadData<T> __Myt;
535 public:
536  typedef T value_type;
537  typedef value_type & reference;
538  typedef const value_type & const_reference;
539  typedef value_type * pointer;
540  typedef const value_type * const_pointer;
541 private:
543  static void Dtor(void * p){__Ptr sp(static_cast<pointer>(p));}
544 public:
545  CThreadData()
546  : key_(PTHREAD_KEYS_MAX)
547  {
548  ::pthread_key_create(&key_, &Dtor);
549  }
550  bool valid() const{return (key_ != PTHREAD_KEYS_MAX);}
551  pointer ptr(){return static_cast<pointer>(getValue());}
552  const_pointer ptr() const{return static_cast<const_pointer>(getValue());}
553  reference ref(){return *ptr();}
554  const_reference ref() const{return *ptr();}
555  std::string toString() const{
556  CToString oss;
557  oss<<"{key_="<<key_<<'}';
558  return oss.str();
559  }
560 private:
561  void * getValue() const{
562  if(!valid())
563  return NULL;
564  void * p = ::pthread_getspecific(key_);
565  if(NULL == p){
566  __Ptr sp(tools::New<value_type>());
567  if(0 == ::pthread_setspecific(key_, sp.get()))
568  p = sp.release();
569  }
570  return p;
571  }
572  //field
573  pthread_key_t key_;
574 };
575 
576 class CBarrier;
577 
579 {
580  friend class CBarrier;
581  typedef CBarrierAttr __Myt;
582 public:
583  CBarrierAttr() throw(std::runtime_error){
584  THROW_RT_IF_FAIL(::pthread_barrierattr_init(&attr_));
585  }
586  ~CBarrierAttr(){
587  ::pthread_barrierattr_destroy(&attr_);
588  }
589  void pshared(bool on) throw(std::runtime_error){
590  THROW_RT_IF_FAIL(::pthread_barrierattr_setpshared(&attr_, (on ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE)));
591  }
592  bool pshared() const throw(std::runtime_error){
593  int on = 0;
594  THROW_RT_IF_FAIL(::pthread_barrierattr_getpshared(&attr_, &on));
595  return (PTHREAD_PROCESS_SHARED == on);
596  }
597 private:
598  const pthread_barrierattr_t * a() const{return &attr_;}
599  CBarrierAttr(const __Myt &); //disable copy and assignment
600  __Myt & operator =(const __Myt &);
601  pthread_barrierattr_t attr_;
602 };
603 
604 class CBarrier
605 {
606  typedef CBarrier __Myt;
607 public:
608  explicit CBarrier(size_t count) throw(std::runtime_error){
609  THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, NULL, count));
610  }
611  CBarrier(size_t count, const CBarrierAttr & attr) throw(std::runtime_error){
612  THROW_RT_IF_FAIL(::pthread_barrier_init(&barrier_, attr.a(), count));
613  }
614  ~CBarrier(){
615  ::pthread_barrier_destroy(&barrier_);
616  }
617  void wait() throw(std::runtime_error){
618  int err = ::pthread_barrier_wait(&barrier_);
619  if(0 != err && PTHREAD_BARRIER_SERIAL_THREAD != err)
620  throw std::runtime_error(tools::ErrorMsg(err).c_str());
621  }
622 private:
623  CBarrier(const __Myt &); //disable copy and assignment
624  __Myt & operator =(const __Myt &);
625  //field
626  pthread_barrier_t barrier_;
627 };
628 
629 NS_SERVER_END
630 
631 #endif
Definition: mutex.hh:604
Definition: to_string.hh:43
Definition: scoped_ptr.hh:10
Definition: mutex.hh:532
Definition: mutex.hh:184
Definition: mutex.hh:73
Definition: mutex.hh:263
Encapsulation for fd (file descriptor) and regular files.
Definition: mutex.hh:332
Definition: mutex.hh:119
Regular file operations.
Definition: file.hh:181
Definition: mutex.hh:211
Definition: mutex.hh:516
Definition: mutex.hh:578
Definition: mutex.hh:430
NS_IMPL::CManipulatorEnd< void, void > end()
End operations for CInByteStream, COutByteStreamStrRef, COutByteStreamVecRef.
Definition: data_stream.hh:929
Definition: mutex.hh:35
Definition: mutex.hh:146
Definition: mutex.hh:292