/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: ConditionVariable.Unix.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "ConditionVariable.Generic.hpp" #include #if !defined(_AURUNTIME_GENERICCV) namespace Aurora::Threading::Primitives { ConditionVariableImpl::ConditionVariableImpl(const AuSPtr &mutex) : mutex_(std::dynamic_pointer_cast(mutex)) { auto ret = pthread_cond_init(&pthreadCv_, NULL); SysAssert(ret == 0, "Couldn't initialize CV"); } ConditionVariableImpl::~ConditionVariableImpl() { pthread_cond_destroy(&pthreadCv_); } AuSPtr ConditionVariableImpl::GetMutex() { return mutex_; } bool ConditionVariableImpl::WaitForSignal(AuUInt32 timeout) { auto mutex = reinterpret_cast(mutex_->GetOSHandle()); if (timeout == 0) { int ret {}; do { if ((ret = pthread_cond_wait(&pthreadCv_, mutex)) == 0) { return true; } } while (ret == EINTR); SysPanic("Couldn't wait on CV {}", ret); return true; } else { struct timespec tspec; Time::ms2tsabs(&tspec, timeout); int ret {}; do { ret = pthread_cond_timedwait(&pthreadCv_, mutex, &tspec); if (ret == 0) { return true; } if (ret == ETIMEDOUT) { return false; } } while (ret == EINTR); SysPanic("conditional timed wait failed {}", ret); return true; } } void ConditionVariableImpl::Signal() { auto ret = pthread_cond_signal(&pthreadCv_); SysAssert(ret == 0, "Couldn't wake any CV waiters"); } void ConditionVariableImpl::Broadcast() { auto ret = pthread_cond_broadcast(&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); } } #endif