From 57d292d962d0de1b35febec71aa1a185e4b461b1 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Thu, 9 Sep 2010 18:00:49 +0400 Subject: [PATCH] Better documentation and error reporting for ThreadSemaphore. --- public-trunk/CommonLibs/Threads.cpp | 65 ++++++++++++++++++++++++++--- public-trunk/CommonLibs/Threads.h | 43 +++++++++++++++---- 2 files changed, 93 insertions(+), 15 deletions(-) diff --git a/public-trunk/CommonLibs/Threads.cpp b/public-trunk/CommonLibs/Threads.cpp index 184c271..0449710 100644 --- a/public-trunk/CommonLibs/Threads.cpp +++ b/public-trunk/CommonLibs/Threads.cpp @@ -28,6 +28,7 @@ #include "Threads.h" #include "Timeval.h" +#include using namespace std; @@ -96,14 +97,66 @@ void Signal::wait(Mutex& wMutex, unsigned timeout) const pthread_cond_timedwait(&mSignal,&wMutex.mMutex,&waitTime); } -/** Wait for semaphore to be signaled with timeout. -* @returns 0 on success, -1 on error or timeout. -*/ -int ThreadSemaphore::wait(unsigned timeout) const +ThreadSemaphore::Result ThreadSemaphore::wait(unsigned timeoutMs) { - Timeval then(timeout); + Timeval then(timeoutMs); struct timespec waitTime = then.timespec(); - return sem_timedwait(&mSem,&waitTime); + int s; + while ((s = sem_timedwait(&mSem,&waitTime)) == -1 && errno == EINTR) + continue; + + if (s == -1) + { + if (errno == ETIMEDOUT) + { + return TSEM_TIMEOUT; + } + return TSEM_ERROR; + } + return TSEM_OK; +} + +ThreadSemaphore::Result ThreadSemaphore::wait() +{ + int s; + while ((s = sem_wait(&mSem)) == -1 && errno == EINTR) + continue; + + if (s == -1) + { + return TSEM_ERROR; + } + return TSEM_OK; +} + +ThreadSemaphore::Result ThreadSemaphore::trywait() +{ + int s; + while ((s = sem_trywait(&mSem)) == -1 && errno == EINTR) + continue; + + if (s == -1) + { + if (errno == EAGAIN) + { + return TSEM_TIMEOUT; + } + return TSEM_ERROR; + } + return TSEM_OK; +} + +ThreadSemaphore::Result ThreadSemaphore::post() +{ + if (sem_post(&mSem) != 0) + { + if (errno == EOVERFLOW) + { + return TSEM_OVERFLOW; + } + return TSEM_ERROR; + } + return TSEM_OK; } void Thread::start(void *(*task)(void*), void *arg) diff --git a/public-trunk/CommonLibs/Threads.h b/public-trunk/CommonLibs/Threads.h index 6bb57bf..9015be8 100644 --- a/public-trunk/CommonLibs/Threads.h +++ b/public-trunk/CommonLibs/Threads.h @@ -126,30 +126,55 @@ class ThreadSemaphore { private: - mutable sem_t mSem; + sem_t mSem; public: - ThreadSemaphore(int pshared = 0, unsigned value = 0) { assert(sem_init(&mSem,pshared,value)!=-1); } + enum Result { + TSEM_OK, ///< Success. + TSEM_TIMEOUT, ///< wait() or trywait() timed out. + TSEM_OVERFLOW, ///< post() overflows a semaphore + TSEM_ERROR ///< Generic error. + }; + + /** Create and initialize semaphore. + * @param[in] value - initial semaphore value. + */ + ThreadSemaphore(unsigned value = 0) + { + int s = sem_init(&mSem,0,value); + assert(s == 0); + } ~ThreadSemaphore() { sem_destroy(&mSem); } /** Wait for semaphore to be signaled with timeout. - * @returns 0 on success, -1 on error or timeout. + * @param[in] timeoutMs - timeout in milliseconds + * + * @retval TSEM_OK on success. + * @retval TSEM_TIMEOUT on timeout. + * @retval TSEM_ERROR on error. */ - int wait (unsigned timeout) const; + Result wait(unsigned timeoutMs); /** Wait for semaphore to be signaled infinitely. - * @returns 0 on success, -1 on error. + * @retval TSEM_OK on success. + * @retval TSEM_ERROR on error. */ - int wait() const { return sem_wait(&mSem); } + Result wait(); /** Check if semaphore has been signaled and disarm it. - * @returns 0 if semaphore has been signaled, -1 in other cases. + * @retval TSEM_OK is semaphore is signaled. + * @retval TSEM_TIMEOUT if semaphore is not signaled. + * @retval TSEM_ERROR on error. */ - int trywait() const { return sem_trywait(&mSem); } + Result trywait(); - int post() { return sem_post (&mSem); } + /** Signal semaphore. + * @retval TSEM_OK on success. + * @retval TSEM_ERROR on error. + */ + Result post(); };