From 17b117e73df71925d73ee026b4f54aa1867ce0a5 Mon Sep 17 00:00:00 2001 From: Jesse Gilles Date: Mon, 20 Apr 2015 16:49:52 -0500 Subject: initial commit --- src/MTS_Condition.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/MTS_Condition.cpp (limited to 'src/MTS_Condition.cpp') diff --git a/src/MTS_Condition.cpp b/src/MTS_Condition.cpp new file mode 100644 index 0000000..d238d50 --- /dev/null +++ b/src/MTS_Condition.cpp @@ -0,0 +1,115 @@ +/* + * 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 +} -- cgit v1.2.3