/* 为优化代码,重新封装部分跨平台IPC; by dzj, 09.04 */ #ifndef DS_LOCK #define DS_LOCK //#define TEST_CODE //测试代码需定义此宏(包含自己的proto副本),gatesrv使用时不定义此宏; #ifdef TEST_CODE #include "proto/CliProtocol.h" #define R_PLAYER CTestPlayer //测试代码使用 #else //TEST_CODE #include "../../Base/PkgProc/CliProtocol.h" #define R_PLAYER CPlayer //GateSrv使用 #endif //TEST_CODE #ifdef WIN32 #define _WIN32_WINNT 0x0500 //to use spincount lock; #ifndef _WINDOWS_ #include #endif //_WINDOWS #define DSCS_SPINCOUNT 500 //循环锁循环次数; //#define DSCS_USESPIN //使用循环锁等待; #include /* _beginthread, _endthread */ typedef unsigned (__stdcall * PTHREAD_START) (void*); #define HXBCBEGINTHREADEX( psa, cbStack, pfnStartAddr\ , pvParam, fdwCreate, pdwThreadID)\ ((HANDLE) _beginthreadex(\ (void*) (psa),\ (unsigned) (cbStack),\ (PTHREAD_START)(pfnStartAddr),\ (void*) (pvParam),\ (unsigned) (fdwCreate),\ (unsigned*) (pdwThreadID))) #ifdef _DEBUG #include #include #define _CRTDBG_MAP_ALLOC void* __cdecl operator new( size_t nSize, const char* lpszFileName, int nLine ); void __cdecl operator delete( void* p, const char*, int ); #define NEW new(__FILE__, __LINE__) //直接使用new定义有编译错误解决不了,虽然在另建的工程中定义new操作符后可以定义new #else //_DEBUG #define NEW new #endif //_DEBUG #else //WIN32 #include #include #include #define NEW new #endif //WIN32 #ifndef WIN32 #include #endif //WIN32 #ifdef WIN32 #define I32 __int32 #define I64 __int64 #else //WIN32 #define I32 int32_t #define I64 int64_t #endif //WIN32 #include #include #include #include #ifdef WIN32 #include #pragma intrinsic(_InterlockedAnd) #pragma intrinsic(_InterlockedOr) #endif //WIN32 ///存储栅栏(全栅栏) static inline void DsMfence() { #ifdef WIN32 __asm mfence; #else //WIN32 __asm__( "mfence" ); #endif //WIN32 } typedef struct DsAtomic { public: inline I32 GetAtomicVal() { return innerVal; } inline void InitAtomicVal( I32 inVal ) { innerVal = inVal; } public: ///原子置bit inline void SetBit(unsigned int bitpos ) { #ifdef WIN32 _InterlockedOr( (long volatile *)&(innerVal), 0x00000001< alloc##notion##Buf;\ std::list< intype* > release##notion##Buf; ///使用标记从TLS中取得notion标记的池对象分配缓存 #define GET_TLS_POOL_ALLOC( notion ) \ ( ( NULL != ThreadGetPriData() ) ? ( &(ThreadGetPriData()->alloc##notion##Buf) ) : NULL ) ///使用标记从TLS中取得notion标记的池对象释放缓存 #define GET_TLS_POOL_RELEASE( notion ) \ ( ( NULL != ThreadGetPriData() ) ? ( &(ThreadGetPriData()->release##notion##Buf) ) : NULL ) #define GET_TLS_LOG() \ ( ( NULL != ThreadGetPriData() ) ? ( ThreadGetPriData()->pTlsLog ) : NULL ) //组解包 #define GET_TLS_CLIPRO() \ ( ( NULL != ThreadGetPriData() ) ? ( ThreadGetPriData()->pRcvClipro ) : NULL ) #ifndef WIN32 //线程异常跳转返回上下文; #define GET_TLS_SIGEXCEPTBUF( pOutSigJmpbuf, isGetOK ) \ { \ ThreadPriData* pTmpPriData = ThreadGetPriData();\ if ( NULL != pTmpPriData )\ {\ isGetOK = true;\ pOutSigJmpbuf = pTmpPriData->pSigJmpbuf;\ } else {\ isGetOK = false;\ pOutSigJmpbuf = NULL;\ }\ } #define SET_TLS_SIGEXCEPTBUF( pInSigJmpbuf, isSetOK ) \ { \ ThreadPriData* pTmpPriData = ThreadGetPriData();\ if ( NULL != pTmpPriData )\ {\ isSetOK = true;\ pTmpPriData->pSigJmpbuf = pInSigJmpbuf;\ } else {\ isSetOK = false;\ }\ } #endif //WIN32 struct TestPoolObj; struct NewMsgToPut; class R_PLAYER; namespace MUX_PROTO { class CliProtocol; }; //测试类型 template< typename T_IN > struct TestTObj; struct TestT; class CDsBufLog;//每线程log; struct ThreadPriData //具体的结构内容随进程的不同而不同 { public: ThreadPriData(); ~ThreadPriData(); public: TLS_POOL_DATA_DECLARE( TestPoolObj, TestPoolObjNO/*使用标记*/ ); TLS_POOL_DATA_DECLARE( TestTObj, TestTObj1NO/*使用标记*/ ); TLS_POOL_DATA_DECLARE( NewMsgToPut, MsgToPutNO/*使用标记*/ ); TLS_POOL_DATA_DECLARE( R_PLAYER, TestPlayerNO/*使用标记*/ ); CDsBufLog* pTlsLog;//日志; MUX_PROTO::CliProtocol* pRcvClipro;//平台组解包; #ifndef WIN32 sigjmp_buf* pSigJmpbuf;//线程异常跳转返回上下文; #endif //WIN32 }; #ifdef WIN32 extern unsigned long g_tlsKey;//全局私有数据键; #else //WIN32 extern pthread_key_t g_tlsKey; #endif //WIN32 void MainInitTls();//全局TLS初始化; void MainEndTls();//全局TLS释放; void ThreadInitTls();//每线程开始时调用以初始化本线程TLS; void ThreadEndTls();//每线程结束时调用以释放本线程TLS相关数据; ThreadPriData* ThreadGetPriData();//得到本线程私有数据指针; class DsNewCS { public: DsNewCS() { InitCS(); }; ~DsNewCS() { ReleaseCS(); }; public: #ifdef WIN32 BOOL InitCS() #else //WIN32 bool InitCS() #endif //WIN32 { #ifdef WIN32 #ifdef DSCS_USESPIN return InitializeCriticalSectionAndSpinCount( &m_hCS, DSCS_SPINCOUNT ); #else //DSCS_USESPIN InitializeCriticalSection( &m_hCS ); return TRUE; #endif //DSCS_USESPIN #else //WIN32 return ( 0 == pthread_mutex_init( &(m_hCS), NULL ) ); #endif //WIN32 } void ReleaseCS() { #ifdef WIN32 DeleteCriticalSection( &m_hCS ); #else //WIN32 pthread_mutex_destroy( &(m_hCS) ); #endif //WIN32 } #ifdef WIN32 CRITICAL_SECTION& GetMutexRef() #else //WIN32 pthread_mutex_t& GetMutexRef() #endif //WIN32 { return m_hCS; } private: #ifdef WIN32 CRITICAL_SECTION m_hCS; #else //WIN32 pthread_mutex_t m_hCS;//互斥锁; #endif //WIN32 }; class DsNewMutex { private: DsNewMutex(); public: explicit DsNewMutex( DsNewCS& inCS ) : m_refMutex( inCS.GetMutexRef() ) { #ifdef WIN32 ::EnterCriticalSection( &m_refMutex ); #else //WIN32 pthread_mutex_lock( &m_refMutex ); #endif //WIN32 } ~DsNewMutex() { #ifdef WIN32 ::LeaveCriticalSection( &m_refMutex ); #else //WIN32 pthread_mutex_unlock( &m_refMutex ); #endif //WIN32 } private: #ifdef WIN32 CRITICAL_SECTION& m_refMutex; #else //WIN32 pthread_mutex_t& m_refMutex;//互斥锁; #endif //WIN32 }; class DsEvent { public: DsEvent() { #ifndef WIN32 pthread_mutex_init( &(m_foolock), NULL ); pthread_cond_init( &(m_sleepcond), NULL ); #else //WIN32 m_sleepevent = ::CreateEvent( NULL, FALSE/*自动重置*/, FALSE/*初始状态未触发*/, NULL ); #endif //WIN32 }; ~DsEvent() { #ifndef WIN32 pthread_cond_destroy( &(m_sleepcond) ); pthread_mutex_destroy( &(m_foolock) ); #else //WIN32 ::CloseHandle( m_sleepevent ); #endif //WIN32 } public: ///阻塞以等待事件; inline void BlockWaitEvent() { #ifndef WIN32 pthread_mutex_lock( &(m_foolock) ); pthread_cond_wait( &(m_sleepcond), &(m_foolock) ); pthread_mutex_unlock( &(m_foolock) ); #else //WIN32 ::WaitForSingleObject( m_sleepevent, INFINITE ); #endif //WIN32 return; } inline void BlockWaitEventByTime( unsigned int waitmsec/*等待的毫秒数*/ ) { #ifndef WIN32 unsigned int secnum = waitmsec / 1000; unsigned int msecnum = waitmsec - secnum*1000 ; struct timespec waittotime;//等待至时刻; struct timeval now; gettimeofday(&now, NULL); waittotime.tv_sec = now.tv_sec + secnum; waittotime.tv_nsec = now.tv_usec * 1000; waittotime.tv_nsec += msecnum*1000; pthread_mutex_lock( &(m_foolock) ); pthread_cond_timedwait( &(m_sleepcond), &(m_foolock), &(waittotime) ); pthread_mutex_unlock( &(m_foolock) ); #else //WIN32 ::WaitForSingleObject( m_sleepevent, waitmsec ); #endif //WIN32 return; } ///通知事件发生,解除可能的阻塞; inline void SignalEvent() { #ifndef WIN32 pthread_cond_signal( &(m_sleepcond) );//通知可能等在条件变量上的读线程; #else //WIN32 ::SetEvent( m_sleepevent ); #endif //WIN32 } private: #ifndef WIN32 pthread_mutex_t m_foolock;//永远不会锁等待,只是为了使用条件变量; pthread_cond_t m_sleepcond;//等待用条件变量; #else //WIN32 HANDLE m_sleepevent;//等待用事件; #endif //WIN32 }; //使用makefile定义,#define USE_CRYPT //使用加解密,没有合适位置,暂放此处; #ifdef USE_CRYPT #pragma pack(push,1) struct StEncDec{ //开启加解密的特殊信息; static const unsigned char CHECKBT1 = 7; static const unsigned char CHECKBT2 = 23; static const unsigned char CHECKBT3 = 97; static const unsigned char CHECKBT4 = 231; public: StEncDec() : pkgLen(sizeof(StEncDec)), checkbt1(CHECKBT1), checkbt2(CHECKBT2), checkbt3(CHECKBT3), checkbt4(CHECKBT4) {}; public: inline bool IsValidStEncDec() { return ( (CHECKBT1 == checkbt1) && (CHECKBT2 == checkbt2) && (CHECKBT3 == checkbt3) && (CHECKBT4 == checkbt4) ); } public: unsigned short pkgLen;//包头(作为包发送时使用); unsigned char checkbt1; unsigned char checkbt2; unsigned char checkbt3; unsigned char checkbt4; }; #pragma pack(pop) #endif //USE_CRYPT #endif //DS_LOCK