Skip to content
Extraits de code Groupes Projets
run.c 9,44 Kio
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

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

#define N 4
//travailler avec des linkendList
typedef struct node{ 
    long value;
    struct node *next;
}node_t;

typedef struct queue{ 
    struct node *tail;
    int size;
    int final;
}queue_t;

struct buffer_rc{
    char *tab[2*N];
    int size;       
    int len;
    int head;
    int tail;
    int stop;
    FILE *file1;
};


struct buffer_cw
{
    queue_t *tab[2*N];
    int size;       
    int len;
    int head;
    int tail;
    int stop;
    FILE *file2;
};

struct buffer_rccw{
    struct buffer_rc *struct1;
    struct buffer_cw *struct2; 
};

/* sémaphore est une structure de donné qui contient :
    *un entier qui stocke la valeur, positive ou nulle du sémaphore.
    *une queue qui contient les pointeurs vers les threads
*/
pthread_mutex_t mutex1;
sem_t empty1;
sem_t full1;

pthread_mutex_t mutex2;
sem_t empty2;
sem_t full2;


void put_in_buffer_1(char *c, struct buffer_rc *ptr){ //ajouter un element dans le buffer 1
    
    ptr->tab[ptr->head] = malloc(sizeof(c)); // on stoxke de espace 
    //ptr->tab[ptr->head] = c;
    strcpy(ptr->tab[ptr->head],c); //copie
    ptr->len++; // augmente l'espace occupé par le buffer
    ptr->head = (ptr->head + 1)%ptr->size; //chaque fois qu'un élément est ajouté, 
    //on augmente le pointeur de 1 mais l'espace du buffer est de 8 donc faire un modulo
    
}

char *get_from_buffer_1(struct buffer_rc *ptr){ // chercher dans le buffer 1
    char *result;
    result = ptr->tab[ptr->tail]; // donne un valeur a result
    //free(ptr->tab[ptr->tail]);
    ptr->tab[ptr->tail] = NULL;
    ptr->len--; //diminue l'espace occupé par le buffer
    ptr->tail = (ptr->tail + 1)%ptr->size;

    return result;
}

void put_in_buffer_2(struct queue *ptr, struct buffer_cw *buf){ //ajouter un element dans le buffer 2
    
    buf->tab[buf->head] = ptr;
    buf->len++; //augmenté l'espace occupé par le buffer
    buf->head = (buf->head + 1)%buf->size;
}

queue_t *get_from_buffer_2(struct buffer_cw *buf){ // trouver un element
    //printf("%d\n",buf->len);
    struct queue *result;
    result = buf->tab[buf->tail]; //donne une valeur a result
    buf->len--; //diminue l'espace occupé par le buffer
    buf->tail = (buf->tail + 1)%buf->size;

    return result;
}


int is_div(long number, long i) { // Vérifie si i est un diviseur de number.
    return (number % i == 0) ; // revoi 0 si le nombre n'est pas divisible par i et 1 si il est divisible
}


int is_prime(long number) { // Vérifie si number est un nombre premier. Return 1 si il est premier, 0 sinon
    if (number != 2) {
        if (number  % 2 == 0) {
            return 0 ;
        }
    }
    for (long i = 3 ; i <= (number/2); i = i + 2) { //regarde les differents nombres pouvant etre diviser number
        if (is_div(number,i) != 0) { // si i peut diviser number
            return 0 ; //renvoi 0 => FAUX
        }
    }
    return 1 ; //sinon => VRAI
}


void enqueue(queue_t* q, long val){ 

    
    struct node *ptr;
    ptr = malloc(sizeof(node_t));
    if (ptr == NULL){
        free(ptr);
        return;}
    ptr -> value = val;
    ptr -> next = malloc(sizeof(node_t));

    if (q->size == 0)
    {
        *q->tail = *ptr;
        *ptr->next = *ptr;
    }
    else{
        *ptr->next = *q->tail->next;
        *q->tail->next = *ptr;
    }
    q->size++;
    //return q;
    free(ptr);

}


queue_t* prime_divs(long number){

    struct queue new_queue;
    new_queue.size = 0;
    new_queue.tail = malloc(sizeof(node_t));
    if(new_queue.tail==NULL){return NULL;}

    struct queue *ptr;
    ptr = malloc(sizeof(queue_t));
    if (ptr == NULL){
        free(new_queue.tail);
        free(ptr);
        return NULL;}
    *ptr = new_queue;

    for (long i = 2; i <= number/2; i++){
        if (is_div(number, i) && is_prime(i) == 1){
            enqueue(ptr,i);
        }
    }
    enqueue(ptr,number);

    return ptr;

}

void *writing(void *param){

    struct buffer_cw *param1 = (struct buffer_cw *) param;
    int stop = 0;
    
    while(param1->stop == 0){            
       
        sem_wait(&full2);
        pthread_mutex_lock(&mutex2);
        queue_t *pr_divs = get_from_buffer_2(param);
        pthread_mutex_unlock(&mutex2);
        sem_post(&empty2); 

        if (pr_divs->final == 1)
        {   
            //printf("final : %d\n",pr_divs->final);
            if (stop == N-1){
                return NULL;
            }
            stop++;
        }
        else{
          

            FILE *file2 = param1->file2;   

            struct node *current;
            current = malloc(sizeof(node_t));
            if (current == NULL){return NULL;}
            *current = *pr_divs->tail;
            current = current->next;

            for (int i = 0; i < pr_divs->size; i++)
            {
                fprintf(file2," %ld",current->value);
                current = current->next;
            }
            fputc('\n',file2);
        }
        

    }
   
    return NULL;
}

void *calculating(void *param){

    struct buffer_rccw *param1 = (struct buffer_rccw *) param;

    struct buffer_rc *buffer_1 = param1->struct1;
    struct buffer_cw *buffer_2 = param1->struct2;
    
    while(buffer_1->stop == 0){  

        sem_wait(&full1);
        pthread_mutex_lock(&mutex1);
        char *chaine = get_from_buffer_1(buffer_1);
        pthread_mutex_unlock(&mutex1);
        sem_post(&empty1);

        if (strcmp("stop",chaine) == 0)
        {   
            struct queue *final;
            final = malloc(sizeof(queue_t));
            if (final == NULL){return NULL;}

            final->final = 1;

            sem_wait(&empty2);
            pthread_mutex_lock(&mutex2);
            put_in_buffer_2(final,buffer_2);    
            pthread_mutex_unlock(&mutex2);
            sem_post(&full2);
            return NULL;
        }
           

        struct queue *pr_divs;
        pr_divs = malloc(sizeof(queue_t));
        if (pr_divs == NULL){return NULL;}

        pr_divs = prime_divs(strtol(chaine,NULL,0));

        sem_wait(&empty2);
        pthread_mutex_lock(&mutex2);
        put_in_buffer_2(pr_divs,buffer_2);    
        pthread_mutex_unlock(&mutex2);
        sem_post(&full2);


    }
    
    return NULL;
}

void *reading (void *param){

    struct buffer_rc *param1= (struct buffer_rc *) param;
    
    char chaine[20];

    FILE *input;
    //input = malloc(sizeof(FILE*));
    input = param1->file1;

    
    while (fgets(chaine,20,input) != NULL){
        
        sem_wait(&empty1);
        pthread_mutex_lock(&mutex1);

        put_in_buffer_1(chaine,param1);            //put each line in the buffer #1
        
        pthread_mutex_unlock(&mutex1);
        sem_post(&full1);
    }
    //param1->stop = 1;

    for (int i = 0; i < N; i++)
    {
        sem_wait(&empty1);
        pthread_mutex_lock(&mutex1);

        put_in_buffer_1("stop\0",param1);            //put each line in the buffer #1
        
        pthread_mutex_unlock(&mutex1);
        sem_post(&full1);
    }
    

    return NULL;

}

void sem_1_initializer(struct buffer_rc *buf){
    pthread_mutex_init(&mutex1,NULL);
    sem_init(&empty1,0,buf->size);
    sem_init(&full1,0,0);

}

void sem_2_initializer (struct buffer_cw *buf){

    pthread_mutex_init(&mutex2,NULL);
    sem_init(&empty2,0,buf->size);
    sem_init(&full2,0,0);

}

struct buffer_rc * buff_init_1(FILE *file1){

    struct buffer_rc *ptr1;
    ptr1 = malloc(sizeof(struct buffer_rc));
    if (ptr1 == NULL){
        free(ptr1);
        return NULL;}
    ptr1->size = 2*N;
    ptr1->len = 0;
    ptr1->head = 0;
    ptr1->tail = 0;
    ptr1->stop = 0;
    ptr1->file1 = file1;
    
    return ptr1;
}

struct buffer_cw * buff_init_2(FILE *file2){

    struct buffer_cw *ptr2;
    ptr2 = malloc(sizeof(struct buffer_cw));
    if (ptr2 == NULL){
        return NULL;}
    ptr2->size = 2*N;
    ptr2->len = 0;
    ptr2->head = 0;
    ptr2->tail = 0;
    ptr2->stop = 0;
    ptr2->file2 = file2;
    
    return ptr2;
}

struct buffer_rccw *buff_init_12(struct buffer_rc *ptr1,struct buffer_cw *ptr2){
    struct buffer_rccw buffer_12;
    buffer_12.struct1 = ptr1;
    buffer_12.struct2 = ptr2;

    struct buffer_rccw *ptr3;
    ptr3 = malloc(sizeof(struct buffer_rccw));
    if (ptr3 == NULL){return NULL;}
    *ptr3 = buffer_12;
    return ptr3;
}

void thread_create_join(struct buffer_rc *ptr1,struct buffer_cw *ptr2,struct buffer_rccw *ptr3){
    pthread_t reader;
    pthread_t calculators[N];
    pthread_t writer;
    pthread_create(&reader,NULL,&reading,ptr1);
    for (int i = 0; i < N; i++)
    {
        pthread_create(&calculators[i],NULL,&calculating,ptr3);
    }
    pthread_create(&writer,NULL,&writing,ptr2);

    pthread_join(reader,NULL);
    for (int i = 0; i < N; i++)
    {
        pthread_join(calculators[i],NULL);
    }
    pthread_join(writer,NULL);
}

int run (char *input,char *output){

    FILE *file1 = NULL;
    FILE *file2 = NULL;

    file1 = fopen(input,"r");
    if (file1 == NULL){return -1;}

    file2 = fopen(output,"w+");
    if (file2 == NULL){
        fclose(file1);
        return -1;
    }

    struct buffer_rc *ptr1 = buff_init_1(file1);
    struct buffer_cw *ptr2 = buff_init_2(file2);
    struct buffer_rccw *ptr3 = buff_init_12(ptr1,ptr2);

    sem_1_initializer(ptr1);
    sem_2_initializer(ptr2);

    thread_create_join(ptr1,ptr2,ptr3);

    fclose(file1);
    fclose(file2);

    return 0;

}
 /* int main() {
     int err = run("input.txt", "actual_output.txt");

     return err;
 } */