Go to the documentation of this file.00001 #include "ibrcommon/config.h"
00002 #include "ibrcommon/thread/Conditional.h"
00003 #include "ibrcommon/thread/Thread.h"
00004 #include <sys/time.h>
00005 #include <unistd.h>
00006
00007 #ifdef __DEVELOPMENT_ASSERTIONS__
00008 #include <cassert>
00009 #endif
00010
00011 #include <pthread.h>
00012
00013 namespace ibrcommon
00014 {
00015 Conditional::Conditional() : Mutex(MUTEX_NORMAL), _abort(false)
00016 {
00017 pthread_cond_init(&cond, &attr.attr);
00018 }
00019
00020 Conditional::~Conditional()
00021 {
00022 pthread_cond_destroy(&cond);
00023 }
00024
00025 bool Conditional::isLocked()
00026 {
00027 try {
00028 trylock();
00029 leave();
00030 return false;
00031 } catch (const ibrcommon::MutexException&) {
00032 return true;
00033 }
00034 }
00035
00036 void Conditional::signal (bool broadcast)
00037 {
00038 #ifdef __DEVELOPMENT_ASSERTIONS__
00039
00040 assert(isLocked());
00041 #endif
00042
00043 int ret = 0;
00044
00045 if (broadcast)
00046 ret = pthread_cond_broadcast( &cond );
00047 else
00048 ret = pthread_cond_signal( &cond );
00049 }
00050
00051 void Conditional::wait(size_t timeout) throw (ConditionalAbortException)
00052 {
00053 #ifdef __DEVELOPMENT_ASSERTIONS__
00054
00055 assert(isLocked());
00056 #endif
00057
00058 if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
00059
00060 if (timeout == 0)
00061 {
00062 pthread_cond_wait( &cond, &m_mutex );
00063 if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
00064 }
00065 else
00066 {
00067 struct timespec ts;
00068 gettimeout(timeout, &ts);
00069 wait(&ts);
00070 if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
00071 }
00072 }
00073
00074 void Conditional::wait(struct timespec *ts) throw (ConditionalAbortException)
00075 {
00076 #ifdef __DEVELOPMENT_ASSERTIONS__
00077
00078 assert(isLocked());
00079 #endif
00080
00081 if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
00082
00083 int ret = pthread_cond_timedwait(&cond, &m_mutex, ts);
00084
00085 if(ret == ETIMEDOUT)
00086 {
00087 throw ConditionalAbortException(ConditionalAbortException::COND_TIMEOUT, "conditional wait timed out");
00088 }
00089 else if (ret != 0)
00090 {
00091 throw ConditionalAbortException(ConditionalAbortException::COND_ERROR, "error on locking conditional mutex");
00092 }
00093
00094 if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
00095 }
00096
00097 Conditional::attribute Conditional::attr;
00098
00099 Conditional::attribute::attribute()
00100 {
00101 pthread_condattr_init(&attr);
00102
00103 #if _POSIX_TIMERS > 0 && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
00104 #if defined(_POSIX_MONOTONIC_CLOCK)
00105 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
00106 #else
00107 pthread_condattr_setclock(&attr, CLOCK_REALTIME);
00108 #endif
00109 #endif
00110 }
00111
00112 void Conditional::gettimeout(size_t msec, struct timespec *ts)
00113 {
00114 #if _POSIX_TIMERS > 0 && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
00115 #if defined(_POSIX_MONOTONIC_CLOCK)
00116 clock_gettime(CLOCK_MONOTONIC, ts);
00117 #else
00118 clock_gettime(CLOCK_REALTIME, ts);
00119 #endif
00120 #else
00121 timeval tv;
00122 ::gettimeofday(&tv, NULL);
00123 ts->tv_sec = tv.tv_sec;
00124 ts->tv_nsec = tv.tv_usec * 1000l;
00125 #endif
00126 ts->tv_sec += msec / 1000;
00127 ts->tv_nsec += (msec % 1000) * 1000000l;
00128 while(ts->tv_nsec > 1000000000l) {
00129 ++ts->tv_sec;
00130 ts->tv_nsec -= 1000000000l;
00131 }
00132 }
00133
00134 void Conditional::abort()
00135 {
00136 #ifdef __DEVELOPMENT_ASSERTIONS__
00137
00138 assert(isLocked());
00139 #endif // __DEVELOPMENT_ASSERTIONS__
00140
00141 signal(true);
00142 _abort = true;
00143 }
00144
00145 void Conditional::reset()
00146 {
00147 _abort = false;
00148 }
00149 }
00150