#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

#define V(XX) sem_post(&(XX))
#define P(XX) sem_wait(&(XX))

#define N 10

int tete = 0; // indice du buffer pour l'écriture
int queue = 0; // indice du buffer pour la lecture
int buffer[10]; // le buffer

sem_t libre;
sem_t occupe;

static void * fn_ecriture ()
{
    int cpt = 0;

    while(1) {
        // a chaque écriture on décrémente le sémaphore libre et incrémente le sémaphore occupe
        P(libre);
        printf("--------------- Ecriture ---------------\n");
        buffer[tete] = cpt;
        printf("Ecriture [%d] : %d\n\n", tete, cpt);
        // etant donné que le buffer est circulaire, on applique le modulo pour ne pas dépasser la taille du tableau.
        tete = (tete + 1) % N;
        V(occupe);
        cpt++;
    }
    return NULL;
}

static void * fn_lecture ()
{
    while(1) {
        // a chaque lecture on décrémente le sémaphore occupe et incrémente le sémaphore libre
        P(occupe);
        printf("--------------- Lecture ---------------\n");
        printf("Lecture [%d] : %d\n\n", queue, buffer[queue]);
        // on indique que la case est libre pour l'écriture
        buffer[queue] = -1;
        // Modulo pour le buffer circulaire
        queue = (queue + 1) % N;
        V(libre);
    }
    return NULL;
}

int main()
{
    pthread_t ecriture;
    pthread_t lecture;

    // on initialise les deux sémaphore,
    sem_init(&libre, 0, 10);
    sem_init(&occupe, 0, 0);

    // on crée les threads
    pthread_create(&ecriture, NULL, fn_ecriture, NULL);
    pthread_create(&lecture, NULL, fn_lecture, NULL);

    // pn attends que les threads se terminent avant de fermer le programme
    pthread_join(ecriture, NULL);
    pthread_join(lecture, NULL);

    return 0;
}
