-
Lou Davila authoredLou Davila authored
tp.c 7.37 KiB
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <time.h>
#define CAMION_CAPACITE 4
typedef struct {
sem_t velos;
sem_t bornes;
int velos_dispo;
int personnes_attente;
pthread_mutex_t mutex;
} Site;
int SITES, HABITANTS, TRAJETS, BORNES;
Site *sites;
pthread_mutex_t mutex_trajets = PTHREAD_MUTEX_INITIALIZER;
int trajets_effectues = 0;
int velos_depot = 0;
pthread_mutex_t mutex_velos_depot = PTHREAD_MUTEX_INITIALIZER;
void *habitant(void *arg) {
int id = *(int *)arg;
int site_actuel = rand() % SITES;
free(arg);
for (int i = 0; i < TRAJETS; i++) {
int site_suivant;
do {
site_suivant = rand() % SITES;
} while (site_suivant == site_actuel);
pthread_mutex_lock(&sites[site_actuel].mutex);
sites[site_actuel].personnes_attente++;
pthread_mutex_unlock(&sites[site_actuel].mutex);
printf("(GET) Habitant %d attend un vélo au site %d\n", id, site_actuel);
sem_wait(&sites[site_actuel].velos);
pthread_mutex_lock(&sites[site_actuel].mutex);
sites[site_actuel].velos_dispo--;
sites[site_actuel].personnes_attente--;
pthread_mutex_unlock(&sites[site_actuel].mutex);
printf("(GET) Habitant %d prend un vélo au site %d\n", id, site_actuel);
sem_post(&sites[site_actuel].bornes);
//usleep((rand() % 1000 + 1000));
pthread_mutex_lock(&sites[site_suivant].mutex);
sites[site_suivant].personnes_attente++;
pthread_mutex_unlock(&sites[site_suivant].mutex);
printf("(PUT) Habitant %d attend d'avoir accès à une borne du site %d\n", id, site_suivant);
sem_wait(&sites[site_suivant].bornes);
pthread_mutex_lock(&sites[site_suivant].mutex);
sites[site_suivant].velos_dispo++;
sites[site_suivant].personnes_attente--;
pthread_mutex_unlock(&sites[site_suivant].mutex);
sem_post(&sites[site_suivant].velos);
printf("(PUT) Habitant %d dépose un vélo au site %d\n", id, site_suivant);
//usleep((rand() % 1000 + 1000));
site_actuel = site_suivant;
pthread_mutex_lock(&mutex_trajets);
trajets_effectues++;
pthread_mutex_unlock(&mutex_trajets);
}
return NULL;
}
void *gestion_camion(void *arg) {
int velos_camion = 2;
while (1) {
pthread_mutex_lock(&mutex_trajets);
if (trajets_effectues >= HABITANTS * TRAJETS) {
pthread_mutex_unlock(&mutex_trajets);
printf("Camion arrête son travail, tous les trajets sont effectués.\n");
break;
}
pthread_mutex_unlock(&mutex_trajets);
for (int i = 0; i < SITES; i++) {
pthread_mutex_lock(&sites[i].mutex);
// Fixed truck logic - ensure atomic operations with proper locking
if (sites[i].velos_dispo > BORNES - 2 && velos_camion < CAMION_CAPACITE) {
int aRetirer = sites[i].velos_dispo - (BORNES - 2);
if (aRetirer > CAMION_CAPACITE - velos_camion)
aRetirer = CAMION_CAPACITE - velos_camion;
// Ensure we don't remove too many bikes
if (aRetirer > sites[i].velos_dispo-1)
aRetirer = sites[i].velos_dispo-1;
for (int j = 0; j < aRetirer; j++) {
sem_wait(&sites[i].velos);
sites[i].velos_dispo--;
velos_camion++;
sem_post(&sites[i].bornes);
}
printf("Camion prend des vélos au site %d (Vélos dans camion: %d)\n", i, velos_camion);
}
else if (sites[i].velos_dispo < 2 && velos_camion > 0) {
int bikes_to_add = 2 - sites[i].velos_dispo;
if (bikes_to_add > velos_camion)
bikes_to_add = velos_camion;
int available_slots = BORNES - sites[i].velos_dispo;
if (bikes_to_add > available_slots)
bikes_to_add = available_slots;
for (int j = 0; j < bikes_to_add; j++) {
sem_wait(&sites[i].bornes);
sites[i].velos_dispo++;
velos_camion--;
sem_post(&sites[i].velos);
}
printf("Camion dépose des vélos au site %d (Vélos dans camion: %d)\n", i, velos_camion);
}
pthread_mutex_unlock(&sites[i].mutex);
usleep((rand() % 100 + 100));
}
pthread_mutex_lock(&mutex_velos_depot);
if (velos_camion > 2) {
velos_depot += (velos_camion - 2);
velos_camion = 2;
printf("Camion vide les vélos au dépôt (Vélos en dépôt: %d)\n", velos_depot);
} else if (velos_camion < 2 && velos_depot > 0) {
int needed = 2 - velos_camion;
if (needed > velos_depot)
needed = velos_depot;
velos_depot -= needed;
velos_camion += needed;
printf("Camion prend des vélos du dépôt (Vélos en dépôt: %d)\n", velos_depot);
}
pthread_mutex_unlock(&mutex_velos_depot);
printf("Camion fait un tour, vélos restants: %d, vélos en dépôt: %d\n", velos_camion, velos_depot);
usleep((rand() % 100 + 100));
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 5) {
fprintf(stderr, "Usage: %s <SITES> <HABITANTS> <TRAJETS> <BORNES>\n", argv[0]);
return 1;
}
SITES = atoi(argv[1]);
HABITANTS = atoi(argv[2]);
TRAJETS = atoi(argv[3]);
BORNES = atoi(argv[4]);
srand(time(NULL));
sites = malloc(SITES * sizeof(Site));
pthread_t habitants[HABITANTS], camion;
for (int i = 0; i < SITES; i++) {
sem_init(&sites[i].velos, 0, BORNES - 2);
sem_init(&sites[i].bornes, 0, 2);
pthread_mutex_init(&sites[i].mutex, NULL);
sites[i].velos_dispo = BORNES - 2;
sites[i].personnes_attente = 0;
}
for (int i = 0; i < HABITANTS; i++) {
int *id = malloc(sizeof(int));
*id = i;
pthread_create(&habitants[i], NULL, habitant, id);
}
pthread_create(&camion, NULL, gestion_camion, NULL);
for (int i = 0; i < HABITANTS; i++) {
pthread_join(habitants[i], NULL);
}
pthread_join(camion, NULL);
int total_velos = velos_depot;
for (int i = 0; i < SITES; i++) {
total_velos += sites[i].velos_dispo;
printf("Site %d contains %d bykes\n", i, sites[i].velos_dispo);
}
total_velos+= 2;
printf("Nombre total de vélos à la fin : %d (doit être %d)\n", total_velos, SITES * (BORNES - 2) + 2);
printf("Simulation terminée.\n");
for (int i = 0; i < SITES; i++) {
sem_destroy(&sites[i].velos);
sem_destroy(&sites[i].bornes);
pthread_mutex_destroy(&sites[i].mutex);
}
pthread_mutex_destroy(&mutex_trajets);
pthread_mutex_destroy(&mutex_velos_depot);
free(sites);
return 0;
}