IBR-DTNSuite
0.8
|
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