/* Program to shuffle a small deck of cards. */ /* Usage: cc -pthread -o shuffler shuffler.c */ /* ./shuffler */ /* Written by Carey Williamson, Oct 24/2008 */ /* This version uses three threads of control: */ /* - shuffler1 thread moves items around */ /* - shuffler2 thread moves items around */ /* - printer thread prints out array */ #include #include #define ARRAY_SIZE 4 #define LOOP_LIMIT 20 /* global variable shared by all threads */ int deck_of_cards[ARRAY_SIZE]; void *printer(); /* the thread for printing */ void *shuffler1(); /* the thread for shuffling */ void *shuffler2(); /* the thread for shuffling */ /* Mutual exclusion (mutex) locks for thread coordination */ pthread_mutex_t array_location_mutex[ARRAY_SIZE]; int main(int argc, char *argv[]) { pthread_t tid1, tid2, tid3; /* thread identifiers */ pthread_attr_t attr; /* set of thread attributes */ int i; /* Initialize */ for( i = 0; i < ARRAY_SIZE; i++ ) { deck_of_cards[i] = i+1; pthread_mutex_init(&array_location_mutex[i], NULL); } srandom(time(NULL)); /* get the default attributes */ pthread_attr_init(&attr); /* create the first worker thread */ pthread_create(&tid1, &attr, printer, NULL); /* create the second worker thread */ pthread_create(&tid2, &attr, shuffler1, NULL); /* create the third worker thread */ pthread_create(&tid3, &attr, shuffler2, NULL); /* wait for the first worker thread to exit */ pthread_join(tid1, NULL); /* wait for the second worker thread to exit */ pthread_join(tid2, NULL); /* wait for the third worker thread to exit */ pthread_join(tid3, NULL); /* output the final result */ printf("All done, folks!\n"); } /* One thread to handle printing the array */ void *printer() { int i, counter; for( counter = 0; counter < LOOP_LIMIT; counter++ ) { printf("Current contents of array: "); for( i = 0; i < ARRAY_SIZE; i++ ) printf(" %d", deck_of_cards[i]); printf("\n"); /* wait for a bit before next iteration */ sleep( random() % 5 ); } pthread_exit(0); } /* One thread to handle shuffling */ void *shuffler1() { int index1, index2, temp; int counter; for( counter = 0; counter < LOOP_LIMIT; counter++ ) { index1 = random() % ARRAY_SIZE; index2 = random() % ARRAY_SIZE; while( index2 == index1 ) { index2 = random() % ARRAY_SIZE; } printf("Shuffler 1 iter %d: switching %d at pos %d with %d at pos %d\n", counter, deck_of_cards[index1], index1, deck_of_cards[index2], index2); if( index1 < index2) { pthread_mutex_lock(&array_location_mutex[index1]); sleep(1); pthread_mutex_lock(&array_location_mutex[index2]); } else { pthread_mutex_lock(&array_location_mutex[index2]); sleep(1); pthread_mutex_lock(&array_location_mutex[index1]); } temp = deck_of_cards[index1]; deck_of_cards[index1] = deck_of_cards[index2]; deck_of_cards[index2] = temp; pthread_mutex_unlock(&array_location_mutex[index1]); pthread_mutex_unlock(&array_location_mutex[index2]); /* wait for a bit before next iteration */ sleep( random() % 5 ); } pthread_exit(0); } /* Another thread to handle shuffling */ void *shuffler2() { int index1, index2, temp; int counter; for( counter = 0; counter < LOOP_LIMIT; counter++ ) { index1 = random() % ARRAY_SIZE; index2 = random() % ARRAY_SIZE; while( index2 == index1 ) index2 = random() % ARRAY_SIZE; printf("Shuffler 2 iter %d: switching %d at pos %d with %d at pos %d\n", counter, deck_of_cards[index1], index1, deck_of_cards[index2], index2); if( index1 < index2) { pthread_mutex_lock(&array_location_mutex[index1]); pthread_mutex_lock(&array_location_mutex[index2]); } else { pthread_mutex_lock(&array_location_mutex[index2]); pthread_mutex_lock(&array_location_mutex[index1]); } temp = deck_of_cards[index1]; deck_of_cards[index1] = deck_of_cards[index2]; deck_of_cards[index2] = temp; pthread_mutex_unlock(&array_location_mutex[index1]); pthread_mutex_unlock(&array_location_mutex[index2]); /* wait for a bit before next iteration */ sleep( random() % 5 ); } pthread_exit(0); }