/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Mutex.Unix.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "Mutex.Generic.hpp" #if !defined(_AURUNTIME_GENERICMUTEX) #include "Mutex.Unix.hpp" #include namespace Aurora::Threading::Primitives { Mutex::Mutex() { auto status = pthread_mutex_init(&this->value_, nullptr) == 0; SysAssert(status, "Mutex init failed"); } Mutex::~Mutex() { int status = pthread_mutex_destroy(&this->value_); RUNTIME_ASSERT_SHUTDOWN_SAFE(status == 0, "Mutex destruct failed, {} {}", status, errno); } bool Mutex::HasOSHandle(AuMach &mach) { mach = reinterpret_cast(&this->value_); return true; } bool Mutex::TryLock() { return pthread_mutex_trylock(&this->value_) == 0; } bool Mutex::HasLockImplementation() { return true; } void Mutex::Lock() { auto status = Lock(0); SysAssert(status, "Couldn't lock Mutex object"); } bool Mutex::Lock(AuUInt64 timeout) { if (timeout == 0) { int ret {}; do { if ((ret = pthread_mutex_lock(&this->value_)) == 0) { return true; } } while (ret == EINTR); SysPanic("mutex lock failed {}", ret); } else { struct timespec tspec; Time::ms2tsabs(&tspec, timeout); int ret {}; do { ret = pthread_mutex_timedlock(&this->value_, &tspec); if (ret == 0) { return true; } if (ret == ETIMEDOUT) { return false; } } while (ret == EINTR); SysPanic("mutex timed lock failed {}", ret); return true; } } void Mutex::Unlock() { auto status = pthread_mutex_unlock(&this->value_) == 0; SysAssert(status, "Mutex release error"); } AUKN_SYM IWaitable *MutexNew() { return _new Mutex(); } AUKN_SYM void MutexRelease(IWaitable *waitable) { AuSafeDelete(waitable); } } #endif