// Includes #include #include #include #include #include // Constantes #define NB_PERS_MAX 100 #define NB_ATTRACTION 5 #define TIME_ATTRAC_MAX 12 #define PERS_MAX_ATTRAC 10 #define TPS_OUVERTURE_PARC 120 #define ARGENT_MAX 50 #define COUT_MAX 2 // Definition du type state correspondant // aux états qu'une personne peut avoir typedef enum { ARR = 0, FREE, PAY, QUIT }STATE; // Définition de la structure personne typedef struct { int id; STATE etat; int temps; // temps passé dans le parc d'attractions int money; // Optionnel }PERSONNE; // Définition de la structure Attraction gratuite typedef struct { int id; int visite; }ATTRACTION_FREE; // Définition de la structure attraction payante typedef struct { int id; int capacite; // Capacité de l'attraction int temps; // Durée de l'attraction int visite; int cout; // Optionnel }ATTRACTION_PAY; // Structure permmettant de stocker l'id et le nombre de visite de l'attraction la plus visitée typedef struct { int max; int id; }SEARCHMAX; // Variables globales // Tableau de sémaphore sem_t* sem; ATTRACTION_PAY* tabAttrac_P; ATTRACTION_FREE* tabAttrac_F; int nbAttrac_P; int nbAttrac_F; int temps; // Prototypes des handlers void * handlerAttrac (void*); void * handlerPers (void*); int timer (void); int main (void) { /// Déclarations int nbPers; int i; SEARCHMAX maxAP; SEARCHMAX maxAF; int somme = 0; PERSONNE* tabPers; pthread_t* tabThreadP; // Une personne correspond à un thread // Une attraction payante correspond à un thread pthread_t* tabThreadAttrac_P; // Définition des nombres aléatoires // Génère un nombre aléatoire de personnes entre 1 et 100 nbPers = rand()%NB_PERS_MAX+1; // Génère un nombre aléatoire d'attraction payante entre 1 et 4 nbAttrac_P = (rand()%(NB_ATTRACTION-1)) + 1; // Les attractions qui restent sont donc gratuites nbAttrac_F = NB_ATTRACTION - nbAttrac_P; // Allocation dynamique pour les personnes tabPers = (PERSONNE*) malloc (nbPers*sizeof (PERSONNE)); tabThreadP = (pthread_t*) malloc (nbPers*sizeof (pthread_t)); // Allocation dynamique pour les attractions payantes tabAttrac_P = (ATTRACTION_PAY*) malloc (nbAttrac_P*sizeof (ATTRACTION_PAY)); tabThreadAttrac_P = (pthread_t*) malloc (nbAttrac_P*sizeof (pthread_t)); // Allocation dynamique pour les attractions gratuites tabAttrac_F = (ATTRACTION_FREE*) malloc (nbAttrac_F*sizeof (ATTRACTION_FREE)); // Allocation dynamique du tableau de semaphore sem = (sem_t*) malloc (nbAttrac_P*sizeof (sem_t)); // Initialisation des structures personnes for (i = 0; i < nbPers; i++) { tabPers[i].id = i; tabPers[i].etat = ARR; // Toutes les personnes arrivent tabPers[i].temps = 0; // Gestion du temps passé dans le parc tabPers[i].money = rand ()%ARGENT_MAX; } // Initialisation des structures attractions payantes et des semaphores for (i = 0; i < nbAttrac_P; i++) { tabAttrac_P[i].id = i; tabAttrac_P[i].temps = rand()%TIME_ATTRAC_MAX+1; tabAttrac_P[i].capacite = rand()%PERS_MAX_ATTRAC+1; tabAttrac_P[i].visite = 0; tabAttrac_P[i].cout = rand()%COUT_MAX+1 ; sem_init (&sem[i], 0, rand()%PERS_MAX_ATTRAC+1); } // Initialisation des structures attractions gratuites for (i = 0; i < nbAttrac_F; i++) { tabAttrac_F[i].id = i; tabAttrac_P[i].visite = 0; } puts ("Bienvenue à DigiWorld ! : OUVERTURE DES PORTES DU PARC"); // Création des threads pour les personnes for (i = 0; i < nbPers; i++) pthread_create (&tabThreadP[i], NULL, handlerPers, &tabPers[i]); // Création des threads pour les attractions payantes for (i = 0; i < nbAttrac_P; i++) pthread_create (&tabThreadAttrac_P[i], NULL, handlerAttrac, NULL); // Attente des threads while (temps < TPS_OUVERTURE_PARC) timer(); for (i = 0; i < nbPers; i++) pthread_join(tabThreadP[i], NULL); for (i = 0; i < nbAttrac_P; i++) pthread_join(tabThreadAttrac_P[i], NULL); // Expulsion des personnes for (i = 0; i < nbPers; i++) { tabPers[i].etat = QUIT; // Toutes les personnes partent somme += tabPers[i].temps; } puts ("DigiWorld : A Bientot ! : FERMETURE DES PORTES DU PARC"); // Recherche des max dans les deux types d'attractions maxAP.max = 0; maxAP.id = 0; maxAF.max = 0; maxAF.id = 0; // Attractions payantes for ( i = 0 ; i < nbAttrac_P ; i++) { if (tabAttrac_P[i].visite > maxAP.max) { maxAP.max = tabAttrac_P[i].visite; maxAP.id = i; } else { maxAP.max = maxAP.max; maxAP.id = maxAP.id; } } // Attractions gratuites for ( i = 0 ; i < nbAttrac_F ; i++) { if (tabAttrac_F[i].visite > maxAF.max) { maxAF.max = tabAttrac_F[i].visite; maxAF.id = i; } } // Résumé de la journée printf ("%d personnes ont visité le parc aujourd'hui \n", nbPers); printf ("et ont passé en moyenne %d min %d s dans le parc \n", (somme/nbPers)/60, (somme/nbPers)%60); if (nbAttrac_F > 0) printf ("L'attraction gratuite la plus visitée est l'attraction %d avec %d visites\n", maxAF.id, maxAF.max); printf ("L'attraction payante la plus visitée est l'attraction %d avec %d visites\n", maxAP.id, maxAP.max); // Libération de la mémoire free (tabPers); free (tabThreadP); free (tabAttrac_P); free (tabThreadAttrac_P); free (tabAttrac_F); return 0; } // Fonction qui compte le temps int timer () { sleep(1); return ++temps; } // Fonction pour les threads des attractions payantes void * handlerAttrac (void* personne) { int ind; PERSONNE * p = (PERSONNE *) personne; float tmpn; int actuelTemps; // Indice aléatoir du tableau ind = rand()%nbAttrac_P; // Vérification si la personne est solvable tmpn = p->money - tabAttrac_P[ind].cout; if (tmpn < 0) { p->etat = (rand ()%2)+1; handlerPers(p); return; } else { actuelTemps = temps; // TQ que le parc est ouvert on essaye de faire une prise de sémaphore while (temps < TPS_OUVERTURE_PARC) { while (sem_wait (&sem[ind]) == -1); } if (temps >= TPS_OUVERTURE_PARC) { p->etat = QUIT; return; } else { tabAttrac_P[ind].visite++; p->money -= tabAttrac_P[ind].cout; p->temps += temps - actuelTemps; return; } } } void * handlerPers (void* visiteur) { PERSONNE* pers = (PERSONNE*) visiteur; // TQ on ne dépasse pas le temps d'ouverture du parc while (temps <= TPS_OUVERTURE_PARC) { // Selon l'état dans lequel la personne se trouve... switch (pers->etat) { case ARR : // Etat initial // Changement d'état pers->etat = (rand ()%2)+1; return; break; case FREE: // Etat Attraction libre // Incrémentation du temps pers->temps += (rand()%TPS_OUVERTURE_PARC)+1; // +1 visite tabAttrac_F [(rand ()%nbAttrac_F)+1].visite++; // Changement d'état pers->etat = (rand ()%3)+1; return; break; case PAY : // Etat Attraction payante handlerAttrac(pers); return; break; case QUIT : // Quitte Digiworld return; break; } } pers->etat = QUIT; return; }