#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
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 <teams> <members>\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;
}