Multithreaded-Concurrency-Operating-Systems-Project / problem1.c
problem1.c
Raw
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <stdbool.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;           // One lock for all threads
pthread_cond_t cond_soccerLeads = PTHREAD_COND_INITIALIZER; // In case there are other pair leaders for soccer
pthread_cond_t cond_s = PTHREAD_COND_INITIALIZER;           // Conditon to wake up soccder bunk bed
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER;           // Conditon to wake up baseball bunk bed
pthread_cond_t cond_f = PTHREAD_COND_INITIALIZER;           // Conditon to wake up football bunk bed
pthread_cond_t cond_feild_clear = PTHREAD_COND_INITIALIZER; // Waiting for game to start, as a leader
pthread_cond_t cond_inGame = PTHREAD_COND_INITIALIZER;      // Playing a game, as a follower

int num_on_feild = 0;        // Number of people allowed to be on the feild
int num_on_feild_actual = 0; // Number of people actually on the feild
int num_s, num_b, num_f;     // The number of players in the bunkbed for each sport
int game_duration = 0;       // in seconds

bool active_soccer_game = 0; //

int global_thread_id = 0;
pthread_t soccer[44];
pthread_t football[44];
pthread_t baseball[36];

void *try_to_leave()
{
    // pthread_mutex_lock(&lock);
    num_on_feild_actual--;
    printf("Player left the field. There are %i players on the field\n", num_on_feild_actual);
    if (num_on_feild_actual == 0)
    {
        num_on_feild = 0;
        pthread_cond_signal(&cond_feild_clear);
        printf("GAME is Over. Sent a signal let in the next leader!\n");
    }
    pthread_mutex_unlock(&lock);
}

void *try_to_queue(void *arg)
{
    int player_type = (int)arg;
    int *num = 0;
    int feild_max = 0;
    int num_req = 0;
    pthread_cond_t *cond;
    char gameName[10] = "";
    switch (player_type)
    {
    case 0:
        strcpy(gameName, "SOCCER");
        num = &num_s;
        cond = &cond_s;
        num_req = 2;
        feild_max = 22;
        break;
    case 1:
        strcpy(gameName, "BASEBALL");
        num = &num_b;
        cond = &cond_b;
        num_req = 18;
        feild_max = 18;
        break;
    case 2:
        strcpy(gameName, "FOOTBALL");
        num = &num_f;
        cond = &cond_f;
        num_req = 22;
        feild_max = 22;
        break;
    default:
        printf("Broke\n");
    }

    pthread_mutex_lock(&lock);
    int myID = global_thread_id;
    global_thread_id++;
    pthread_mutex_unlock(&lock);
    printf("[%s Player %d] I have been created!\n", gameName, myID);

    int number_of_games_to_play_per_person = 2;
    for (int j = 0; j < number_of_games_to_play_per_person; j++)
    {
        int arrivalTime = (rand() % 5) + 1;
        printf("[%s Player %d] My random sleep time is %d secconds...\n", gameName, myID, arrivalTime);
        sleep(arrivalTime);
        printf("[%s Player %d] I am awake after %d secconds.\n", gameName, myID, arrivalTime);

        pthread_mutex_lock(&lock);
        (*num)++;

        printf("[%s Player %d] Including myself, my bed has %d people. I neeed %d people to start.\n", gameName, myID, *num, num_req);
        if (*num == num_req || (player_type == 0 && *num % 2 == 0) || (player_type != 0 && *num == num_req * 2))
        {
        POINT2:
            if (num_on_feild == 0)
            {
                pthread_cond_broadcast(cond);
                printf("[%s Player %d] I am a leader and I will start my game with %d people.\n", gameName, myID, num_req);
                num_on_feild += num_req;
                (*num) -= num_req;
                num_on_feild_actual++;

                if (player_type == 0)
                {
                    // You are starting a soccer game
                    printf("[%s Player %d] This game is a soccer game, I need to wake up other soccer leaders. \n", gameName, myID);
                    active_soccer_game = 1;
                    pthread_cond_broadcast(&cond_soccerLeads);
                }

                game_duration = (rand() % 5) + 1;
                printf("%s GAME STARTED with %i players by [%s Player %d] for %i secconds. \n", gameName, num_req, gameName, myID, game_duration);
                pthread_mutex_unlock(&lock);
                sleep(game_duration);
                pthread_mutex_lock(&lock);
                active_soccer_game = 0;
                pthread_cond_broadcast(&cond_inGame);
                try_to_leave();
            }
            else if (active_soccer_game == 1 && player_type == 0 && num_on_feild < feild_max)
            {
                // You are joning a exsiting soccer game
                printf("[%s Player %d] I am a fake soccer leader and I will add %i people to the soccer game which had %i people.\n", gameName, myID, num_req, num_on_feild);
                pthread_cond_broadcast(cond);
                num_on_feild += num_req;
                (*num) -= num_req;
                num_on_feild_actual++;
                printf("[%s Player %d] I'm waiting for the game to end...' \n", gameName, myID);
                pthread_cond_wait(&cond_inGame, &lock);
                // pthread_mutex_unlock(&lock);
                try_to_leave();
            }
            else
            {
                if (player_type == 0 && (*num) > num_req && (*num) != feild_max + num_req)
                {
                    printf("[%s Player %d] There %i soccer players waiting. Since there is already an leader, I will wait in a soccerLeads queue to become a fake leader. \n", gameName, myID, *num);
                    pthread_cond_wait(&cond_soccerLeads, &lock);
                }
                else
                {
                    printf("[%s Player %d] I am a leader but I cannot start a game until the feild is clear. I'm waiting to be called when it is. \n", gameName, myID);
                    pthread_cond_wait(&cond_feild_clear, &lock);
                }
                printf("[%s Player %d] I have been realeased from my queue. Going to POINT 2.\n", gameName, myID);
                goto POINT2;
            }
        }
        else
        {
        POINT:
            printf("[%s Player %d] I am not a leader and I will wait in my bed for %d people. \n", gameName, myID, num_req);
            pthread_cond_wait(cond, &lock);
            if (num_on_feild_actual < num_on_feild)
            {
                num_on_feild_actual++;
                printf("[%s Player %d] I was woken up and I moved to the feild. I am player %i out of %i.\n", gameName, myID, num_on_feild_actual, num_on_feild);
                pthread_cond_wait(&cond_inGame, &lock);
                // pthread_mutex_unlock(&lock);
                printf("[%s Player %d] I have been released from the game. I am leaving the feild.\n", gameName, myID);
                try_to_leave();
            }
            else
            {
                printf("[%s Player %d] I was woken up but I cannot move to the feild because it is full. I will go back to sleep. \n", gameName, myID);
                goto POINT;
            }
        }
    }

    printf("[%s Player %d] I am leaving the program since I have played %i games.\n", gameName, myID, number_of_games_to_play_per_person);
}

int main()
{

    // Open seed file
    FILE *fp;
    char seed[5];

    fp = fopen("seed.txt", "r");

    // getting seed from file
    fscanf(fp, "%s", seed);

    int intseed = atoi(seed);

    // seed srand
    srand((unsigned)intseed);

    // close file
    fclose(fp);

    printf("Seed is %i \n", intseed);
    printf("Each player will play 2 games. You can end the program at any time by pressing ctrl+c. Games will start in 5 secconds...\n");
    sleep(5);

    // soccer
    for (int i = 0; i < 44; i++)
    {
        pthread_create(&soccer[i], NULL, try_to_queue, (void *)0);
    }

    // baseball
    for (int i = 0; i < 36; i++)
    {
        pthread_create(&baseball[i], NULL, try_to_queue, (void *)1);
    }

    // football
    for (int i = 0; i < 44; i++)
    {
        pthread_create(&football[i], NULL, try_to_queue, (void *)2);
    }

    for (int i = 0; i < 44; i++)
    {
        pthread_join(soccer[i], NULL);
    }

    for (int i = 0; i < 36; i++)
    {
        pthread_join(baseball[i], NULL);
    }

    for (int i = 0; i < 44; i++)
    {
        pthread_join(football[i], NULL);
    }

    printf("All threads have finished\n");
}