#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; } }