/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuSemaphore.Unix.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "AuSemaphore.Generic.hpp" #include "AuSemaphore.Unix.hpp" #if !defined(_AURUNTIME_GENERIC_SEMAPHORE) && !defined(AURORA_IS_XNU_DERIVED) #include namespace Aurora::Threading::Primitives { Semaphore::Semaphore(long intialValue) { auto status = sem_init(&this->value_, 0, intialValue) == 0; SysAssert(status, "Semaphore init failed"); } Semaphore::~Semaphore() { int status = sem_destroy(&this->value_); RUNTIME_ASSERT_SHUTDOWN_SAFE(status == 0, "Semaphore destroy failed: {} {}", status, errno); } bool Semaphore::HasOSHandle(AuMach &mach) { mach = reinterpret_cast(&this->value_); return true; } bool Semaphore::HasLockImplementation() { return true; } bool Semaphore::TryLock() { return sem_trywait(&this->value_) == 0; } bool Semaphore::Lock(AuUInt64 timeout) { if (timeout == 0) { int ret {}; do { if ((ret = sem_wait(&this->value_)) == 0) { return true; } } while (errno == EINTR); SysPanic("semaphore lock failed {}", errno); return true; } else { struct timespec tspec; Time::ms2tsabs(&tspec, timeout); int ret {}; do { ret = sem_timedwait(&this->value_, &tspec); if (ret == 0) { return true; } if (errno == ETIMEDOUT) { return false; } } while (errno == EINTR); SysPanic("semaphore timed lock failed"); return true; } } void Semaphore::Lock() { auto status = Lock(0); SysAssert(status, "Couldn't lock semaphore"); } void Semaphore::Unlock(long count) { for (int i = 0; i < count; i++) { Unlock(); } } void Semaphore::Unlock() { auto status = sem_post(&this->value_) == 0; SysAssert(status, "Semaphore release error"); } AUKN_SYM ISemaphore *SemaphoreNew(int initialCount) { return _new Semaphore(initialCount); } AUKN_SYM void SemaphoreRelease(ISemaphore *waitable) { AuSafeDelete(waitable); } } #endif