📄 wymutex.cpp
字号:
/* Copyright is licensed under GNU LGPL. by I.J.Wang 2003*/#define WYLIB_SOURCE#include "wymutex.h"#include <exception>// [Internal] Wy__MutexAttr defines a class for use by WyMutex(constructor)// execlusively.//class Wy__MutexAttr { public: Wy__MutexAttr(WyMutex::MutexType k) WY__TSPC(); ~Wy__MutexAttr() WY__TSPC() { ::pthread_mutexattr_destroy(&_attr); }; const ::pthread_mutexattr_t* attr(void) const WY__TSPC() { return &_attr; }; private: ::pthread_mutexattr_t _attr; Wy__MutexAttr(); // not to use};// [Internal] Class is only used to declare const static object//Wy__MutexAttr::Wy__MutexAttr(WyMutex::MutexType k) WY__TSPC()try { int v=::pthread_mutexattr_init(&_attr); if(v!=0) { WY_TERMINATE(""); // man. always return 0 } switch(k) { case WyMutex::Fast: if((v=::pthread_mutexattr_settype(&_attr,PTHREAD_MUTEX_FAST_NP))!=0) { ::pthread_mutexattr_destroy(&_attr); WY_TERMINATE(""); // man. says only EINVAL } break; case WyMutex::ErrorCheck: if((v=::pthread_mutexattr_settype(&_attr,PTHREAD_MUTEX_ERRORCHECK_NP))!=0) { ::pthread_mutexattr_destroy(&_attr); WY_TERMINATE(""); // man. says only EINVAL } break; case WyMutex::Recursive: if((v=::pthread_mutexattr_settype(&_attr,PTHREAD_MUTEX_RECURSIVE_NP))!=0) { ::pthread_mutexattr_destroy(&_attr); WY_TERMINATE(""); // man. says only EINVAL } break; default: ::pthread_mutexattr_destroy(&_attr); WY_TERMINATE(""); }}catch(...) { WY_TERMINATE("");};//----------------------------------------------------------------------------//// Define the Wy__MutexAttr objects for WyMutex in constructor.//static const Wy__MutexAttr MutexAttr_Fast(WyMutex::Fast);static const Wy__MutexAttr MutexAttr_ErrorCheck(WyMutex::ErrorCheck);static const Wy__MutexAttr MutexAttr_Recursive(WyMutex::Recursive);const char WyMutex::class_name[]="WyMutex";// Construct the mutex//// (POSIX mutex may fail, implement is supposed to be restricted version)//WyMutex::WyMutex(MutexType t) WY__TSPC(Reply)try : _sig(WY_NONE_ID){ int v; switch(t) { case Fast: v=::pthread_mutex_init(&_mtx,MutexAttr_Fast.attr()); if(v!=0) { WY_TERMINATE(""); // man. says always 0 }; break; case ErrorCheck: v=::pthread_mutex_init(&_mtx,MutexAttr_ErrorCheck.attr()); if(v!=0) { WY_TERMINATE(""); // man. says always 0 } break; case Recursive: v=::pthread_mutex_init(&_mtx,MutexAttr_Recursive.attr()); if(v!=0) { WY_TERMINATE(""); // man. says always 0 } break; default: WY_TERMINATE(""); // MutexType changed, but code not updated. } #ifndef NDEBUG _sig=WYMUTEX_ID; #endif}catch(const WyMutex::Reply&) { throw;}catch(...) { WY_TERMINATE("");};WyMutex::~WyMutex() WY__TSPC(){ #ifndef NDEBUG if(_sig!=WYMUTEX_ID) { WY_TERMINATE(""); } // Note: Further access of the object cause stack unwind or probably SIGSEGV // signal // _sig=WY_NONE_ID; #endif for(int i=0; i<30000; ++i) { // better have a long limit const int v=::pthread_mutex_destroy(&_mtx); if(v==0) { return; // succeed } // // man. indicates may fail of EBUSY // if(v==EBUSY) { Wy__Base::yield(); // yield should be ok continue; } break; } WY_TERMINATE("");};WyRet WyMutex::lock(void) WY__TSPC(){ #ifndef NDEBUG if(_sig!=WYMUTEX_ID) { WY_TERMINATE(""); } #endif const int v=::pthread_mutex_lock(&_mtx); if(v!=0) { WY_RETURN( WyRet(WyReply(v)) ); } return(Ok);};WyRet WyMutex::trylock(void) WY__TSPC(){ #ifndef NDEBUG if(_sig!=WYMUTEX_ID) { WY_TERMINATE(""); } #endif const int v=::pthread_mutex_trylock(&_mtx); if(v!=0) { WY_RETURN( WyRet(WyReply(v)) ); } return(Ok);};WyRet WyMutex::unlock(void) WY__TSPC(){ #ifndef NDEBUG if(_sig!=WYMUTEX_ID) { WY_TERMINATE(""); } #endif // On my Linux platform: // 1. unlock ErrorCheck kind of WyMutex in unlocked state gets EPERM // 2. unlock Fast kind of WyMutex in unlocked state gets 0 // const int v=::pthread_mutex_unlock(&_mtx); if(v!=0) { WY_RETURN( WyRet(WyReply(v)) ); } return(Ok);};void WyMutex::lock(WyMutex &mtx) WY__TSPC(Reply){ #ifndef NDEBUG if(mtx._sig!=WYMUTEX_ID) { WY_TERMINATE(""); } #endif const int v=::pthread_mutex_lock(&mtx._mtx); if(v!=0) { WY_THROW( Reply(WyReply(v)) ); }};void WyMutex::trylock(WyMutex &mtx) WY__TSPC(Reply){ #ifndef NDEBUG if(mtx._sig!=WYMUTEX_ID) { WY_TERMINATE(""); } #endif const int v=::pthread_mutex_trylock(&mtx._mtx); if(v!=0) { WY_THROW( Reply(WyReply(v)) ); }};void WyMutex::unlock(WyMutex &mtx) WY__TSPC(Reply){ #ifndef NDEBUG if(mtx._sig!=WYMUTEX_ID) { WY_TERMINATE(""); } #endif const int v=::pthread_mutex_unlock(&mtx._mtx); if(v!=0) { WY_THROW( Reply(WyReply(v)) ); }};::pthread_mutex_t* WyMutex::wy_mutex_ptr(void) WY__TSPC(){ return &_mtx;};//------------------------------------------------const char WyLock::class_name[]="WyLock";WyLock::WyLock(WyMutex &mtx) WY__TSPC(Reply) :_pmtx(NULL){ WyRet r( mtx.lock() ); if(r!=Ok) { WY_THROW( Reply(r) ); } _pmtx=&mtx;};WyLock::~WyLock() WY__TSPC(){#ifndef NDEBUG if(_pmtx==NULL) { WY_TERMINATE(""); }#endif const WyRet r(_pmtx->unlock()); if(r!=Ok) { // none of the manpage listed EPERM/EINVAL should occur WY_TERMINATE(""); } _pmtx=NULL; };WyRet WyLock::xlock(WyMutex& mtx){#ifndef NDEBUG if(_pmtx==NULL) { WY_THROW( WyRet(Wym_EFAULT) ); }#endif WyRet r( mtx.lock() ); if(r!=Ok) { WY_RETURN(r); } if((r=_pmtx->unlock())!=Ok) { // manual listed errno's EINVAL/EPERM indicate 'internal' error mtx.unlock(); WY_THROW(r); } _pmtx=&mtx; return(Ok);};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -