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