Mutex的简单封装
/* * CMutex.h * Process level lock */ #ifndef UTIL_MUTEX_H #define UTIL_MUTEX_H #include "../common/Common.h" class CMutex { public: /** * Check if mutex exists */ static int Exists( const char * pszName, bool * bExist, int proj_id = -1/* Linux only */ ); public: CMutex(); ~CMutex(); const char * GetName() const { return m_strName.c_str(); } /** * Open mutex */ int OpenIt( const char * pszName, int proj_id = -1 /* Linux Only */ ); /** * Create mutex if not exists */ int Create( const char * pszName, int proj_id = -1 /* Linux Only */ ); void Lock(); void Unlock(); private: CMutex(const CMutex &); CMutex & operator=(const CMutex &); private: static std::string m_str_path; std::string m_strName; #if defined(_WIN32) HANDLE m_hMutex; #endif #if defined(_LINUX) int m_sem_id; #endif }; template<class TYPE> class CMutexGuard { public: CMutexGuard(TYPE & rTheMutex):m_Mutex(rTheMutex) { m_Mutex.Lock(); } ~CMutexGuard() { m_Mutex.Unlock(); } private: CMutexGuard(); //CMutexGuard(const CMutexGuard &); //CMutexGuard & operator=(const CMutexGuard &); private: TYPE& m_Mutex; }; #endif // _MUTEX_H
/* * CMutex * Process level lock */ #include "CMutex.h" #include "../common/Common.h" #include "Logger.h" /************************************************************************/ /* Windows */ /************************************************************************/ int CMutex::Exists( const char * pszName, bool * bExist, int proj_id/* Linux only */ ) { //Windows #if defined(_WIN32) DWORD dwErrCode = 0; HANDLE hMutex = ::OpenMutexA(MUTEX_ALL_ACCESS, FALSE, pszName); dwErrCode = GetLastError(); if (hMutex == NULL) { if (dwErrCode == ERROR_FILE_NOT_FOUND) { *bExist = false; return 0; } else { *bExist = true; return 0; } } ::CloseHandle(hMutex); *bExist = true; return 0; #endif #if defined(_LINUX) key_t key = ftok(pszName, proj_id); if (key == -1) { return -1; } if (semget(key, 0, 0666) == -1) { if (errno == ENOENT) { *bExist = false; return 0; } else { *bExist = true; return 0; } } *bExist = true; return 0; #endif } CMutex::CMutex() { #if defined(_WIN32) m_hMutex = NULL; #endif #if defined(_LINUX) m_sem_id = -1; #endif } CMutex::~CMutex() { #if defined(_WIN32) if (m_hMutex != NULL) { ::CloseHandle(m_hMutex); m_hMutex = NULL; } #endif #if defined(_LINUX) if (m_sem_id != -1) { //Do not delete //semctl(m_sem_id, 0, IPC_RMID, NULL); m_sem_id = -1; } #endif } /** * Open mutex */ int CMutex::OpenIt( const char * pszName, int proj_id/* Linux Only */ ) { m_strName = pszName; #if defined(_WIN32) DWORD dwErrCode = 0; //Try to open a mutex with name xxx, if not found then create one. m_hMutex = ::OpenMutexA(MUTEX_ALL_ACCESS, FALSE, m_strName.c_str()); dwErrCode = GetLastError(); if (m_hMutex == NULL) { LOG_ERR("CMutex::OpenMutexA %s failed, err=%d", m_strName.c_str(), dwErrCode); return -1; } return 0; #endif #if defined(_LINUX) if (proj_id == -1) { LOG_ERR("Invalid proj_id:%d", proj_id); return -1; } key_t key = ftok(m_strName.c_str(), proj_id); if (-1 == key) { return -1; } m_sem_id = semget(key, 1, 00666); if (m_sem_id == -1) { LOG_ERR("CMutex::semget failed, err=%d", errno); return -1; } return 0; #endif } /** * Create mutex if not exists */ int CMutex::Create( const char * pszName, int proj_id /* Linux Only */ ) { m_strName = pszName; //Windows #if defined(_WIN32) DWORD dwErrCode = 0; //Try to open a mutex with name xxx, if not found then create one. m_hMutex = ::OpenMutexA(MUTEX_ALL_ACCESS, FALSE, m_strName.c_str()); dwErrCode = GetLastError(); if (m_hMutex == NULL) { if (dwErrCode == ERROR_FILE_NOT_FOUND) { // Windows security info, create a empty security, so that the others // can assess it SECURITY_ATTRIBUTES secAttr; char secDesc[SECURITY_DESCRIPTOR_MIN_LENGTH]; secAttr.nLength = sizeof(secAttr); secAttr.bInheritHandle = FALSE; secAttr.lpSecurityDescriptor = &secDesc; InitializeSecurityDescriptor(secAttr.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(secAttr.lpSecurityDescriptor, TRUE, 0, FALSE); m_hMutex = ::CreateMutexA(&secAttr, FALSE, m_strName.c_str()); dwErrCode = GetLastError(); if (NULL == m_hMutex) { LOG_TRACE("CreateMutex %s failed, err=%d", m_strName.c_str(), dwErrCode); return -1; } return 0; } else { LOG_TRACE("OpenMutex %s failed, err=%d", m_strName.c_str(), dwErrCode); return -1; } } return 0; #endif #if defined(_LINUX) if (proj_id == -1) { LOG_TRACE("Invalid proj_id:%d", proj_id); return -1; } key_t key = ftok(m_strName.c_str(), proj_id); if (-1 == key) { return -1; } m_sem_id = semget(key, 1, IPC_CREAT | IPC_EXCL | 00666); if (m_sem_id == -1) { if (errno != EEXIST) { LOG_TRACE("semget(create) failed,err=%d", errno); return -1; } m_sem_id = semget(key, 1, IPC_CREAT | 00666); if (m_sem_id == -1) { LOG_TRACE("semget(open) failed,err=%d", errno); return -1; } } else { //New semaphore created union semu { int val; }; semu arg; arg.val = 1; if (semctl(m_sem_id, 0, SETVAL, arg) == -1) { LOG_TRACE("semctl failed, err=%d", errno); semctl(m_sem_id, 0, IPC_RMID, NULL); m_sem_id = -1; return -1; } return 0; } return 0; #endif } void CMutex::Lock() { #if defined(_WIN32) ::WaitForSingleObject(m_hMutex, INFINITE); #endif #if defined(_LINUX) struct sembuf lock; lock.sem_num = 0; lock.sem_op = -1; lock.sem_flg = SEM_UNDO; semop(m_sem_id, &lock, 1); #endif } void CMutex::Unlock() { #if defined(_WIN32) ::ReleaseMutex(m_hMutex); #endif #if defined(_LINUX) struct sembuf unlock; unlock.sem_num = 0; unlock.sem_op = 1; unlock.sem_flg = SEM_UNDO; semop(m_sem_id, &unlock, 1); #endif }