TeThreadSignal.cpp

Go to the documentation of this file.
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     // Create a manual-reset event.
00023     event_ = CreateEvent (NULL,  // no security
00024                           TRUE,  // manual-reset
00025                           FALSE, // non-signaled initially
00026                           NULL); // unnamed
00027     
00028   #elif TePLATFORM == TePLATFORMCODE_LINUX || TePLATFORM == TePLATFORMCODE_AIX || TePLATFORM == TePLATFORMCODE_APPLE
00029 
00030     /* Creating mutex */
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     /* Creating condition variable */
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       // Release all the threads in this generation.
00079       release_count_ =  waiters_count_;
00080 
00081       // Start a new generation.
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     // Avoid race conditions.
00105     waiters_count_lock_.lock();
00106 
00107     // Increment count of waiters.
00108     waiters_count_++;
00109 
00110     // Store current generation in our activation record.
00111     int my_generation =  wait_generation_count_;
00112 
00113     waiters_count_lock_.unLock();
00114 
00115     for (;;) {
00116       // Wait until the event is signaled.
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       // Exit the loop when the < event_> is signaled and
00131       // there are still waiting threads from this <wait_generation>
00132       // that haven't been released from this wait yet.
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       // We're the last waiter to be notified, so reset the manual event.
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         /* seconds */
00167         timespecstr.tv_sec = timevalstr.tv_sec + ( waiting_time / 1000 );
00168         /* nano-seconds */
00169         timespecstr.tv_nsec = ( timevalstr.tv_usec * 1000 ) +
00170           ( ( waiting_time % 1000 ) * 1000000 );
00171 
00172         if( pthread_cond_timedwait( &condition_var_, &m_access_, 
00173           &timespecstr ) != 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 

Generated on Sun Jul 29 04:01:28 2012 for TerraLib - Development Source by  doxygen 1.5.3