1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
#include <pthread.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
static pthread_mutex_t counter_mx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t zero_cv = PTHREAD_COND_INITIALIZER;
static int counter = 10;
static unsigned int seed = clock();
static void *countdown_cb( void *v )
{
const char *name = reinterpret_cast<const char*>( v );
bool done = false, needToBroadcast = false;
int usecs = 0;
while ( true ) {
pthread_mutex_lock( &counter_mx );
if ( (done = ( counter==0 )) ) break;
usecs = (int)(10.0 * rand_r( &seed ) / RAND_MAX) + 1;
needToBroadcast = (--counter==0);
fprintf( stderr, "[%s] %d\n", name, counter );
pthread_mutex_unlock( &counter_mx );
usleep( usecs );
}
if ( needToBroadcast )
pthread_cond_broadcast( &zero_cv );
pthread_mutex_unlock( &counter_mx );
return NULL;
}
static void *waiting_cb( void *v )
{
const char *name = reinterpret_cast<const char*>( v );
bool done = false;
while ( !done ) {
pthread_mutex_lock( &counter_mx );
fprintf( stderr, "[%s] waiting\n", name );
// pthread_cond_timedwait() for non-blocking
pthread_cond_wait( &zero_cv, &counter_mx );
done = ( counter==0 );
if ( done ) fprintf( stderr, "[%s] done\n", name );
pthread_mutex_unlock( &counter_mx );
}
return NULL;
}
int main()
{
pthread_t a, b, c, d;
pthread_create( &d, NULL, waiting_cb, const_cast<char*>( "thread d" ));
pthread_create( &a, NULL, countdown_cb, const_cast<char*>( "thread a" ));
pthread_create( &b, NULL, countdown_cb, const_cast<char*>( "thread b" ));
pthread_create( &c, NULL, countdown_cb, const_cast<char*>( "thread c" ));
pthread_join( a, NULL );
pthread_join( b, NULL );
pthread_join( c, NULL );
pthread_join( d, NULL );
return 0;
}
|