/* * Copyright (C) 2015 by Multi-Tech Systems * * This file is part of libmts. * * libmts is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * libmts is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libmts. If not, see . * */ #include #include #include #include #include #include #include using namespace MTS; Condition::Condition(Lock* pLock) : m_pLock(pLock) { if (pLock == 0) { throw std::invalid_argument("Condition| constructing lock is null"); } #ifdef WIN32 m_apCondition.reset(CreateEvent(NULL, FALSE, FALSE, NULL)); if (m_pCondition.get() == NULL) { throw std::bad_alloc(); } #else m_apCondition.reset(new pthread_cond_t()); const uint32_t result = pthread_cond_init(m_apCondition.get(), NULL); if (result != 0) { throw std::runtime_error("Condition| failed to initialize condition"); } #endif } Condition::~Condition() { if (!m_apCondition.isNull()) { #ifdef WIN32 const BOOL ok = CloseHandle(m_apCondition.get()); assert(ok); #else const uint32_t result = pthread_cond_destroy(m_apCondition.get()); if (result != 0) { printWarning("Condition| failed to destroy condition"); } assert(result == 0); #endif } } void Condition::wait() { #ifdef WIN32 wait(INFINITE); #else const uint32_t result = pthread_cond_wait(m_apCondition.get(), m_pLock->m_apMutex.get()); if (result != 0) { printWarning("Condition| failed to wait on condition"); } assert(result == 0); #endif } void Condition::wait(uint32_t millis) { assert(m_pLock->isLocked()); if(!m_pLock->isLocked()) { printWarning("Condition| lock was not locked. not waiting on signal."); return; } #ifdef WIN32 ResetEvent(m_apCondition.get()); m_pLock->unlock(); const DWORD waitResult = WaitForSingleObject(m_apCondition.get(), millis); assert(waitResult == WAIT_OBJECT_0 || waitResult == WAIT_TIMEOUT); m_pLock->lock(); #else timespec abstime; int64_t micros = System::timeMicros() + (millis * 1000); abstime.tv_sec = static_cast(micros / 1000000); abstime.tv_nsec = static_cast((micros % 1000000) * 1000); const uint32_t result = pthread_cond_timedwait(m_apCondition.get(), m_pLock->m_apMutex.get(), &abstime); if (result != 0 && result != ETIMEDOUT) { printWarning("Condition| failed to time wait on condition"); } assert(result == 0 || result == ETIMEDOUT); #endif } void Condition::signal() { #ifdef WIN32 const BOOL ok = SetEvent(m_apCondition.get()); assert(ok); #else const uint32_t result = pthread_cond_broadcast(m_apCondition.get()); if (result != 0) { printWarning("Condition| failed to signal condition"); } assert(result == 0); #endif }