IBR-DTNSuite  0.8
ibrcommon/ibrcommon/thread/Conditional.cpp
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                 // assert a locked Conditional
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                 // assert a locked Conditional
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                 // assert a locked Conditional
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                 // assert a locked Conditional
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