#include #include #include using namespace std; #include #include #define CHECK(x) \ { \ int res = x; \ if (res != 0) cerr << "PTHREAD ERROR: " << res << endl; \ } /** * mutex accessible by all threads */ pthread_mutex_t mutex; // Number of tires produced int counter_tires = 0; // Number of motors produced int counter_motors = 0; // stop execution of all threads bool terminate_threads = false; /** * Thread that produces tires every minute (here we use * 1 second instead of one minute). * We simply increment the number of tires produced */ void *thread_inc_tires(void *argument) { while (!terminate_threads) { CHECK( pthread_mutex_lock(&mutex) ); ++counter_tires; cout << "create tire, #tires=" << counter_tires << endl; CHECK( pthread_mutex_unlock(&mutex) ); sleep(1); } CHECK( pthread_mutex_lock(&mutex) ); cout << "terminate thread_inc_tires" << endl; CHECK( pthread_mutex_unlock(&mutex) ); } /** * Thread that produces motors every 5 minutes (here we use * 5 seconds instead of 5 minutes). * We simply increment the number of motors produced */ void *thread_inc_motors(void *argument) { while (!terminate_threads) { CHECK( pthread_mutex_lock(&mutex) ); ++counter_motors; cout << "create motor, #motors=" << counter_motors << endl; CHECK( pthread_mutex_unlock(&mutex) ); sleep(5); } CHECK( pthread_mutex_lock(&mutex) ); cout << "terminate thread_inc_motors" << endl; CHECK( pthread_mutex_unlock(&mutex) ); } /** * Thread that produces cars * We simply wait for at least 4 tires and 1 motor, then * we decrease the number of tires, the number of motors * and increase the number of cars. * We stop all threads as soon as we produce 3 cars. */ void *thread_create_car(void *argument) { int counter_cars = 0; while (counter_cars < 3) { // critical section CHECK( pthread_mutex_lock(&mutex) ); if ((counter_tires >= 4) && (counter_motors >= 1)) { counter_tires -= 4; counter_motors -= 1; ++counter_cars; cout << "create car, #cars=" << counter_cars << endl; } CHECK( pthread_mutex_unlock(&mutex) ); sleep(1); } CHECK( pthread_mutex_lock(&mutex) ); terminate_threads = true; CHECK( pthread_mutex_unlock(&mutex) ); } /** * Main function */ int main() { // threads for tires, motors and cars pthread_t t_inc_tires, t_inc_motors, t_create_cars; // create mutex CHECK( pthread_mutex_init(&mutex, NULL) ); // set attribute to indicate that thread is joinable pthread_attr_t attr; CHECK( pthread_attr_init(&attr) ); CHECK( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) ); // create threads CHECK( pthread_create( &t_inc_tires, &attr, thread_inc_tires, (void *) NULL) ); CHECK( pthread_create( &t_inc_motors, &attr, thread_inc_motors, (void *) NULL) ); CHECK( pthread_create( &t_create_cars, &attr, thread_create_car, (void *) NULL) ); // destroy attribute no more necessary pthread_attr_destroy(&attr); // make the join void *status; CHECK( pthread_join(t_create_cars, &status) ); CHECK( pthread_join(t_inc_tires, &status) ); CHECK( pthread_join(t_inc_motors, &status) ); // this line won't be executed until all threads have terminated cout << "!!! END OF PROGRAM !!!!" << endl; // destroy mutex CHECK( pthread_mutex_destroy(&mutex) ); pthread_exit(NULL); return 0; }