/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuConditionVariable.Unix.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "AuConditionVariable.Generic.hpp" #include #if !defined(_AURUNTIME_GENERICCV) namespace Aurora::Threading::Primitives { ConditionVariableImpl::ConditionVariableImpl(const AuSPtr &mutex) : mutex_(std::dynamic_pointer_cast(mutex)) { pthread_condattr_t attr; ::pthread_condattr_init(&attr); ::pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); auto ret = ::pthread_cond_init(&this->pthreadCv_, &attr); SysAssert(ret == 0, "Couldn't initialize CV"); } ConditionVariableImpl::~ConditionVariableImpl() { ::pthread_cond_destroy(&this->pthreadCv_); } AuSPtr ConditionVariableImpl::GetMutex() { return this->mutex_; } bool ConditionVariableImpl::WaitForSignal(AuUInt32 uTimeout) { return WaitForSignalNS(AuMSToNS(uTimeout)); } bool ConditionVariableImpl::WaitForSignalNS(AuUInt64 qwTimeout) { auto mutex = reinterpret_cast(this->mutex_->GetOSHandle()); if (gRuntimeRunLevel >= 5) { return true; } if (timeout == 0) { int ret {}; do { if ((ret = ::pthread_cond_wait(&this->pthreadCv_, mutex)) == 0) { return true; } } while (ret == EINTR); RUNTIME_ASSERT_SHUTDOWN_SAFE(false, "conditional wait failed: {}", ret) return false; } else { struct timespec tspec; Time::auabsns2ts(&tspec, AuTime::CurrentClockNS() + qwTimeout); int ret {}; do { ret = ::pthread_cond_timedwait(&this->pthreadCv_, mutex, &tspec); if (ret == 0) { return true; } if (ret == ETIMEDOUT) { return false; } } while (ret == EINTR); RUNTIME_ASSERT_SHUTDOWN_SAFE(false, "conditional timed wait failed: {}", ret) return false; } } void ConditionVariableImpl::Signal() { auto ret = ::pthread_cond_signal(&this->pthreadCv_); SysAssert(ret == 0, "Couldn't wake any CV waiters"); } void ConditionVariableImpl::Broadcast() { auto ret = ::pthread_cond_broadcast(&this->pthreadCv_); SysAssert(ret == 0, "Couldn't wake any CV waiters"); } AUKN_SYM IConditionVariable *ConditionVariableNew(const AuSPtr &mutex) { return _new ConditionVariableImpl(mutex); } AUKN_SYM void ConditionVariableRelease(IConditionVariable *mutex) { AuSafeDelete(mutex); } AUROXTL_INTERFACE_SOO_SRC(ConditionVariable, ConditionVariableImpl, (const AuSPtr &, pMutex)) } #endif