#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; /** * data structure used to pass argument to thread * which contains the thread id */ typedef struct { int id; char msg[20]; } thread_data_t; /** * thread to execute */ void *thread_code(void *argument) { // convert argument thread_data_t *data = (thread_data_t *) argument; int n_repeat = 5; while (n_repeat) { // critical section // !!!!!!!!!! LOCK !!!!!!!!!! CHECK( pthread_mutex_lock(&mutex) ); cout << "thread(" << pthread_self() <<") "; cout << ", id=" << data->id; cout << ", msg=[" << data->msg << "]"; cout << ", repeat=" << n_repeat << endl; // !!!!!!!!!! UNLOCK !!!!!!!!!! CHECK( pthread_mutex_unlock(&mutex) ); --n_repeat; sleep(1); } } /** * Main function */ int main() { // array of threads pthread_t threads[10]; // array of data for threads thread_data_t data[10]; // 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 for (int i=0; i<10; ++i) { data[i].id = i; sprintf(data[i].msg, "coucou %d", 100 + rand() % 100); CHECK( pthread_create(&threads[i], &attr, thread_code, (void *) &data[i]) ); } // destroy attribute: no necessary any more pthread_attr_destroy(&attr); // perform the join void *status; for (int i=0; i<10; ++i) { CHECK( pthread_join(threads[i], &status) ); } // this line won't be executed until all threads have terminated // their execution cout << "!!! END OF PROGRAM !!!!" << endl; // !!!!!!!!!! destroy mutex !!!!!!!!!! CHECK( pthread_mutex_destroy(&mutex) ); pthread_exit(NULL); return 0; }