///////////////////////////////////////////////////////////// // // threads.cpp // // Jeff Ondich, 4/12/04 // Updated 11/14/05 // // A simple demonstration of the use of pthreads. // This demo uses two binary semaphores to force strict // alternation between a pair of threads. // // Note that the two thread procedures include delay // loops. The point of this is to illustrate the passing // of parameters to the thread procedures via the fourth // pthread_create parameter. // // To compile: // // g++ -Wall -o threads threads.cpp -lpthread // ///////////////////////////////////////////////////////////// #include #include using namespace std; int gSharedCounter = 0; pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutexB = PTHREAD_MUTEX_INITIALIZER; void *threadMainA( void *arg ); void *threadMainB( void *arg ); void delay( int limit ); int main() { pthread_mutex_lock( &mutexB ); pthread_t threadA, threadB; if( pthread_create( &threadA, NULL, threadMainA, (void *)20000 ) != 0 ) { perror( "Can't create thread A" ); exit( 1 ); } if( pthread_create( &threadB, NULL, threadMainB, (void *)10000 ) != 0 ) { perror( "Can't create thread B" ); exit( 1 ); } // Wait for children to return. If you don't wait for them, the // process will return from main(), and thus shut down the whole // process, including the threads. pthread_join( threadA, NULL ); pthread_join( threadB, NULL ); return 0; } void *threadMainA( void *arg ) { while( 1 ) { pthread_mutex_lock( &mutexA ); gSharedCounter++; cerr << "Thread A: " << gSharedCounter << endl; delay( int(arg) ); pthread_mutex_unlock( &mutexB ); } return NULL; } void *threadMainB( void *arg ) { while( 1 ) { pthread_mutex_lock( &mutexB ); gSharedCounter--; cerr << "Thread B: " << gSharedCounter << endl; delay( int(arg) ); pthread_mutex_unlock( &mutexA ); } return NULL; } void delay( int limit ) { for( int j=0; j < limit; j++ ) { for( int k=0; k < limit; k++ ) { } } }