Program Listing for File ipc_named_mutex.h#
↰ Return to documentation for file (ipc_named_mutex.h)
#ifndef IPC_NAMED_MUTEX_H
#define IPC_NAMED_MUTEX_H
#ifdef _WIN32
// Resolve conflict
#pragma push_macro("interface")
#undef interface
#ifndef NOMINMAX
#define NOMINMAX
#endif
//#include <WinSock2.h>
#include <Windows.h>
// Resolve conflict
#pragma pop_macro("interface")
#ifdef GetClassInfo
#undef GetClassInfo
#endif
#elif defined __unix__
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#else
#error OS is not supported!
#endif
#include <string>
#include <cstdlib>
namespace ipc
{
class named_mutex
{
public:
#ifdef _WIN32
using native_handle_type = HANDLE;
#elif defined __unix__
using native_handle_type = sem_t*;
#else
#error OS is not supported!
#endif
named_mutex(const char* szName = nullptr) noexcept;
named_mutex(const named_mutex&) = delete;
named_mutex(named_mutex&& rmtx) noexcept;
~named_mutex();
named_mutex& operator=(const named_mutex&) = delete;
named_mutex& operator=(named_mutex&& rmtx) noexcept;
void lock();
bool try_lock();
void unlock();
const std::string& name() const;
native_handle_type native_handle();
private:
std::string m_ssName;
native_handle_type m_handle;
};
#ifdef _WIN32
inline named_mutex::named_mutex(const char* szName) noexcept : m_handle(nullptr)
{
if (szName)
m_ssName = szName;
else
{
std::srand(static_cast<unsigned>(std::time(nullptr))); // Use current time as seed for random generator
m_ssName = std::string("NAMED_MUTEX_") + std::to_string(std::rand());
}
m_handle = CreateMutexA(nullptr, FALSE, (std::string("Global\\") + m_ssName).c_str());
}
inline named_mutex::named_mutex(named_mutex&& rmtx) noexcept : m_handle(rmtx.m_handle)
{
rmtx.m_handle = nullptr;
}
inline named_mutex::~named_mutex()
{
if (m_handle && m_handle != INVALID_HANDLE_VALUE)
CloseHandle(m_handle);
}
// False positive warning of CppCheck: m_handle is not assigned a value. This is not the case. Suppress the warning.
// cppcheck-suppress operatorEqVarError
inline named_mutex& named_mutex::operator=(named_mutex&& rmtx) noexcept
{
if (m_handle && m_handle != INVALID_HANDLE_VALUE)
CloseHandle(m_handle);
m_handle = rmtx.m_handle;
rmtx.m_handle = nullptr;
return *this;
}
inline void named_mutex::lock()
{
if (m_handle && m_handle != INVALID_HANDLE_VALUE)
WaitForSingleObject(m_handle, INFINITE);
}
inline bool named_mutex::try_lock()
{
if (m_handle && m_handle != INVALID_HANDLE_VALUE)
return WaitForSingleObject(m_handle, 0) == WAIT_OBJECT_0;
else
return false;
}
inline void named_mutex::unlock()
{
if (m_handle && m_handle != INVALID_HANDLE_VALUE)
ReleaseMutex(m_handle);
}
inline const std::string& named_mutex::name() const
{
return m_ssName;
}
inline named_mutex::native_handle_type named_mutex::native_handle()
{
return m_handle;
}
#elif defined __unix__
inline named_mutex::named_mutex(const char* szName) noexcept : m_handle(nullptr)
{
if (szName)
m_ssName = szName;
else
{
std::srand(static_cast<unsigned>(std::time(nullptr))); // Use current time as seed for random generator
m_ssName = std::string("NAMED_MUTEX_") + std::to_string(std::rand());
}
m_handle = sem_open(m_ssName.c_str(), O_CREAT, 0777 /*O_RDWR*/, 1);
}
inline named_mutex::named_mutex(named_mutex&& rmtx) noexcept : m_handle(rmtx.m_handle)
{
rmtx.m_handle = nullptr;
}
inline named_mutex::~named_mutex()
{
if (m_handle)
sem_close(m_handle);
}
// False positive warning of CppCheck: m_handle is not assigned a value. This is not the case. Suppress the warning.
// cppcheck-suppress operatorEqVarError
inline named_mutex& named_mutex::operator=(named_mutex&& rmtx) noexcept
{
if (m_handle)
sem_close(m_handle);
m_handle = rmtx.m_handle;
rmtx.m_handle = nullptr;
return *this;
}
inline void named_mutex::lock()
{
if (m_handle)
sem_wait(m_handle);
}
inline bool named_mutex::try_lock()
{
return m_handle ? sem_trywait(m_handle) >= 0 : false;
}
inline void named_mutex::unlock()
{
if (m_handle)
sem_post(m_handle);
}
inline const std::string& named_mutex::name() const
{
return m_ssName;
}
inline named_mutex::native_handle_type named_mutex::native_handle()
{
return m_handle;
}
#else
#error OS is not supported!
#endif
}
#endif // !defined IPC_NAMED_MUTEX_H