/*
* 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
}