#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; /** * !!!!!!!!!! condition variable !!!!!!!!!! */ pthread_cond_t condition; int counter_tires = 0; int counter_motors = 0; bool terminate_threads = false; /** * Thread to create tires */ void *thread_inc_tires(void *argument) { while (!terminate_threads) { CHECK( pthread_mutex_lock(&mutex) ); ++counter_tires; cout << "create tire, #tires=" << counter_tires << endl; if ((counter_tires >= 4) && (counter_motors >= 1)) { cout << "signal to 'create_car' to inform we can create a car" << endl; // !!!!!!!!!! pthread_cond_signal(&condition); } CHECK( pthread_mutex_unlock(&mutex) ); sleep(1); } CHECK( pthread_mutex_lock(&mutex) ); cout << "terminate thread_inc_tires" << endl; CHECK( pthread_mutex_unlock(&mutex) ); } /** * Thread to produce motors */ void *thread_inc_motors(void *argument) { while (!terminate_threads) { CHECK( pthread_mutex_lock(&mutex) ); ++counter_motors; cout << "create motor, #motors=" << counter_motors << endl; if ((counter_tires >= 4) && (counter_motors >= 1)) { cout << "signal to 'create_car' to inform we can create a car" << endl; // !!!!!!!!!! pthread_cond_signal(&condition); } CHECK( pthread_mutex_unlock(&mutex) ); sleep(5); } CHECK( pthread_mutex_lock(&mutex) ); cout << "terminate thread_inc_motors" << endl; CHECK( pthread_mutex_unlock(&mutex) ); } /** * Thread to produce */ void *thread_create_car(void *argument) { int counter_cars = 0; while (counter_cars < 5) { // critical section CHECK( pthread_mutex_lock(&mutex) ); // !!!!!!!!!! pthread_cond_wait(&condition, &mutex); counter_tires -= 4; counter_motors -= 1; ++counter_cars; cout << "create car, #cars=" << counter_cars << endl; CHECK( pthread_mutex_unlock(&mutex) ); } CHECK( pthread_mutex_lock(&mutex) ); terminate_threads = true; CHECK( pthread_mutex_unlock(&mutex) ); } int main() { // All threads pthread_t t_inc_tires, t_inc_motors, t_create_cars; // create mutex CHECK( pthread_mutex_init(&mutex, NULL) ); pthread_cond_init(&condition, 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; }