EHS/src/system/Semaphore_P.cpp

163 lines
2.9 KiB
C++

#include "ehs/system/Semaphore_P.h"
#include "ehs/Log.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <cerrno>
namespace ehs
{
Semaphore::~Semaphore()
{
if (!Semaphore::IsValid())
return;
if (sem_destroy(&hdl) == -1)
EHS_LOG_INT(LogType::ERR, 0, "Failed to release semaphore with error #" + Str_8::FromNum(errno) + ".");
valid = false;
}
Semaphore::Semaphore()
: hdl{}, valid(false)
{
}
Semaphore::Semaphore(const Str_8& name, const UInt_32 initial)
: BaseSemaphore(name, initial), hdl{}, valid(false)
{
Semaphore::Initialize();
}
Semaphore::Semaphore(const UInt_32 initial)
: BaseSemaphore(initial), hdl{}, valid(false)
{
Semaphore::Initialize();
}
Semaphore::Semaphore(Semaphore&& sem) noexcept
: BaseSemaphore((Semaphore&&)sem), hdl(sem.hdl), valid(sem.valid)
{
sem.hdl = {};
sem.valid = false;
}
Semaphore::Semaphore(const Semaphore& sem)
: BaseSemaphore(sem), hdl{}, valid(false)
{
Semaphore::Initialize();
}
Semaphore& Semaphore::operator=(Semaphore&& sem) noexcept
{
if (this == &sem)
return *this;
Release();
BaseSemaphore::operator=((Semaphore&&)sem);
hdl = sem.hdl;
valid = sem.valid;
sem.hdl = {};
sem.valid = false;
return *this;
}
Semaphore& Semaphore::operator=(const Semaphore& sem)
{
if (this == &sem)
return *this;
Release();
BaseSemaphore::operator=(sem);
hdl = {};
valid = false;
Initialize();
return *this;
}
void Semaphore::Initialize()
{
if (IsValid())
return;
if (GetName().Size())
{
sem_t* result = sem_open("/" + GetName(), O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, GetInitial());
if (!result)
EHS_LOG_INT(LogType::ERR, 0, "Failed to create semaphore with error #" + Str_8::FromNum(errno) + ".");
hdl = *result;
}
else
{
if (sem_init(&hdl, 0, GetInitial()) == -1)
EHS_LOG_INT(LogType::ERR, 0, "Failed to create semaphore with error #" + Str_8::FromNum(errno) + ".");
}
valid = true;
}
void Semaphore::Release()
{
if (!IsValid())
return;
if (sem_destroy(&hdl) == -1)
EHS_LOG_INT(LogType::ERR, 0, "Failed to release semaphore with error #" + Str_8::FromNum(errno) + ".");
hdl = {};
valid = false;
}
void Semaphore::Signal(const UInt_32 inc)
{
if (!IsValid())
return;
if (sem_post(&hdl) == -1)
EHS_LOG_INT(LogType::ERR, 0, "Failed to signal semaphore with error #" + Str_8::FromNum(errno) + ".");
}
bool Semaphore::Wait(const UInt_32 timeout)
{
if (!IsValid())
return false;
int result;
if (timeout == EHS_INFINITE)
{
result = sem_wait(&hdl);
}
else
{
timespec time = {timeout / 1000, timeout % 1000 * 1000000};
result = sem_timedwait(&hdl, &time);
}
if (result == -1)
{
int code = errno;
if (code != ETIMEDOUT)
EHS_LOG_INT(LogType::ERR, 0, "Failed to wait for semaphore with error #" + Str_8::FromNum(errno) + ".");
return false;
}
return true;
}
bool Semaphore::IsValid() const
{
return valid;
}
}