#include #include #include #include #include typedef struct { pthread_mutex_t* m; pthread_cond_t* c; pthread_t t; int member_index; int team_index; int teams; int* alive; int* game_team; int* counter_array; void* rvalue; } thread_cont; void print_team_counter(int* array, int teams) { putchar('['); int i; for(i = 0; i < teams - 1; ++i) printf("%d,", array[i]); // last field value printf("%d", array[teams - 1]); puts("]"); } void* game(void* data) { thread_cont* container = (thread_cont*) data; int chosen_team; // critical section pthread_mutex_lock(container->m); // sleeping before being waked up while(*container->game_team != container->team_index) pthread_cond_wait(container->c, container->m); //sleep(1); --container->counter_array[container->team_index]; --(*container->alive); printf("Team: %d, member: %d has been selected to play, total alive: %d, ", container->team_index, container->member_index, *container->alive); print_team_counter(container->counter_array, container->teams); if(*container->alive > 0) { // choosing my oponent to play do { chosen_team = lrand48() % container->teams; } while(container->counter_array[chosen_team] == 0); printf("\t I am chosing to play with team #%d !\n", chosen_team); *container->game_team = chosen_team; // sending broadcast pthread_cond_broadcast(container->c); } else printf("\tI am last, so I die without playing !\n"); pthread_mutex_unlock(container->m); return (void*)container->member_index; } int main(int argc, char** argv) { // validating options if(argc != 3) { fputs("Usage: team \n", stderr); exit(EXIT_FAILURE); } int teams = atoi(argv[1]); int members = atoi(argv[2]); if(teams == 0 || members == 0) { fputs("Cannot launch team runner with zero in team or member count (or nonnumeric argument) !\n", stderr); exit(EXIT_FAILURE); } // init of mutex and cond variable pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t conditional; pthread_cond_init(&conditional, NULL); // random seed init time_t t; time(&t); srand48((long)t); int alive = teams * members; int team_number = -1; // variable for game choosing int i, j; // array of threads containers int thread_cont_size = sizeof(thread_cont); thread_cont* container_array = (thread_cont*) malloc(teams * members * thread_cont_size); if(container_array == NULL) { fputs("Cannot malloc memory for array of info for threads !\n", stderr); exit(EXIT_FAILURE); } // array for teams int* team_array = malloc(teams * sizeof(int)); if(team_array == NULL) { fputs("Cannot malloc memory for array of team counter !\n", stderr); exit(EXIT_FAILURE); } for(i = 0; i < teams; ++i) team_array[i] = members; // filling init array for(i = 0; i < teams; ++i) for(j = 0; j < members; ++j) { int index = members * i + j; container_array[index].member_index = j; container_array[index].team_index = i; container_array[index].m = &mutex; container_array[index].c = &conditional; container_array[index].teams = teams; container_array[index].game_team = &team_number; container_array[index].counter_array = team_array; container_array[index].alive = &alive; } // creating threads for(i = 0; i < teams; ++i) for(j = 0; j < members; ++j) { int index = members * i + j; pthread_create(&container_array[index].t, NULL, game, &container_array[index]); } // sending initial broadcast team_number = lrand48() % teams; // variable for game choosing printf("Main thread selected to play team #%d !\n", team_number); pthread_cond_broadcast(&conditional); // joining threads for(i = 0; i < teams; ++i) for(j = 0; j < members; ++j) { int index = members * i + j; pthread_join(container_array[index].t, &container_array[index].rvalue); } pthread_mutex_destroy(&mutex); free(container_array); free(team_array); return 0; }