00001 #include "TeThreadSignal.h"
00002
00003 #include "TeAgnostic.h"
00004
00005 #if TePLATFORM == TePLATFORMCODE_MSWINDOWS
00006 #include <stdio.h>
00007 #elif TePLATFORM == TePLATFORMCODE_LINUX || TePLATFORM == TePLATFORMCODE_AIX || TePLATFORM == TePLATFORMCODE_APPLE
00008 #include <sys/time.h>
00009 #include <time.h>
00010 #else
00011 #error "Unsuported plataform"
00012 #endif
00013
00014 TeThreadSignal::TeThreadSignal()
00015 {
00016 #if TePLATFORM == TePLATFORMCODE_MSWINDOWS
00017
00018 waiters_count_ = 0;
00019 wait_generation_count_ = 0;
00020 release_count_ = 0;
00021
00022
00023 event_ = CreateEvent (NULL,
00024 TRUE,
00025 FALSE,
00026 NULL);
00027
00028 #elif TePLATFORM == TePLATFORMCODE_LINUX || TePLATFORM == TePLATFORMCODE_AIX || TePLATFORM == TePLATFORMCODE_APPLE
00029
00030
00031
00032 pthread_mutexattr_t access_attr;
00033 TEAGN_TRUE_OR_THROW( ( pthread_mutexattr_init( &access_attr ) == 0 ),
00034 "Unable to init mutex attributes" );
00035
00036 pthread_mutexattr_settype( &access_attr, PTHREAD_MUTEX_DEFAULT );
00037 TEAGN_TRUE_OR_THROW(
00038 ( pthread_mutex_init( &m_access_, &access_attr ) == 0 ),
00039 "Unable to init mutex" )
00040
00041
00042
00043 TEAGN_TRUE_OR_THROW( ( pthread_cond_init( &condition_var_, 0 ) == 0 ),
00044 "Unable to create a condition variable" );
00045
00046 #else
00047 #error "Unsuported plataform"
00048 #endif
00049 }
00050
00051
00052 TeThreadSignal::~TeThreadSignal()
00053 {
00054 #if TePLATFORM == TePLATFORMCODE_MSWINDOWS
00055
00056 CloseHandle( event_ );
00057
00058 #elif TePLATFORM == TePLATFORMCODE_LINUX || TePLATFORM == TePLATFORMCODE_AIX || TePLATFORM == TePLATFORMCODE_APPLE
00059
00060 pthread_cond_destroy( &condition_var_ );
00061
00062 pthread_mutex_destroy( &m_access_ );
00063
00064 #else
00065 #error "Unsuported plataform"
00066 #endif
00067 }
00068
00069
00070 void TeThreadSignal::emitSignal()
00071 {
00072 #if TePLATFORM == TePLATFORMCODE_MSWINDOWS
00073
00074 waiters_count_lock_.lock();
00075
00076 if ( waiters_count_ > 0) {
00077 SetEvent ( event_);
00078
00079 release_count_ = waiters_count_;
00080
00081
00082 wait_generation_count_++;
00083 }
00084
00085 waiters_count_lock_.unLock();
00086
00087 #elif TePLATFORM == TePLATFORMCODE_LINUX || TePLATFORM == TePLATFORMCODE_AIX || TePLATFORM == TePLATFORMCODE_APPLE
00088
00089 TEAGN_TRUE_OR_THROW( ( pthread_cond_broadcast( &condition_var_ ) == 0 ),
00090 "Error emiting signal" );
00091
00092 #else
00093 #error "Unsupported platform"
00094 #endif
00095 }
00096
00097
00098 bool TeThreadSignal::waitSignal( unsigned int waiting_time )
00099 {
00100 bool return_value = true;
00101
00102 #if TePLATFORM == TePLATFORMCODE_MSWINDOWS
00103
00104
00105 waiters_count_lock_.lock();
00106
00107
00108 waiters_count_++;
00109
00110
00111 int my_generation = wait_generation_count_;
00112
00113 waiters_count_lock_.unLock();
00114
00115 for (;;) {
00116
00117 if( waiting_time == 0 ) {
00118 if( WaitForSingleObject ( event_, INFINITE ) != WAIT_OBJECT_0 ) {
00119 return_value = false;
00120 break;
00121 }
00122 } else {
00123 if( WaitForSingleObject ( event_, waiting_time ) != WAIT_OBJECT_0 ) {
00124 return_value = false;
00125 break;
00126 }
00127 }
00128
00129 waiters_count_lock_.lock();
00130
00131
00132
00133 int wait_done = release_count_ > 0
00134 && wait_generation_count_ != my_generation;
00135 waiters_count_lock_.unLock();
00136
00137 if (wait_done)
00138 break;
00139 }
00140
00141 waiters_count_lock_.lock();
00142 waiters_count_--;
00143 release_count_--;
00144 int last_waiter = release_count_ == 0;
00145 waiters_count_lock_.unLock();
00146
00147 if (last_waiter)
00148
00149 ResetEvent ( event_);
00150
00151 #elif TePLATFORM == TePLATFORMCODE_LINUX || TePLATFORM == TePLATFORMCODE_AIX || TePLATFORM == TePLATFORMCODE_APPLE
00152
00153 TEAGN_TRUE_OR_THROW( ( pthread_mutex_lock( &m_access_ ) == 0 ),
00154 "Unable to lock mutex" );
00155
00156 if( waiting_time == 0 ) {
00157 if( pthread_cond_wait( &condition_var_, &m_access_ ) != 0 ) {
00158 return_value = false;
00159 }
00160 } else {
00161 struct timeval timevalstr;
00162
00163 if( gettimeofday( &timevalstr, 0 ) == 0 ) {
00164 struct timespec timespecstr;
00165
00166
00167 timespecstr.tv_sec = timevalstr.tv_sec + ( waiting_time / 1000 );
00168
00169 timespecstr.tv_nsec = ( timevalstr.tv_usec * 1000 ) +
00170 ( ( waiting_time % 1000 ) * 1000000 );
00171
00172 if( pthread_cond_timedwait( &condition_var_, &m_access_,
00173 ×pecstr ) != 0 ) {
00174
00175 return_value = false;
00176 }
00177 } else {
00178 TEAGN_LOGWARN( "Unable to get the current time" );
00179 return_value = false;
00180 }
00181 }
00182
00183 TEAGN_TRUE_OR_THROW( ( pthread_mutex_unlock( &m_access_ ) == 0 ),
00184 "Unable to unlock mutex" );
00185
00186 #else
00187 #error "Unsuported plataform"
00188 #endif
00189
00190 return return_value;
00191 }
00192