int main(){ int i = 0; wator_t *p = new_wator( "planet.dat"); if ( ! p ) err(1, "Wator"); /* printf( " debug : \n\t'sd'=%d\n\t'sb'=%d\n\t'fb'=%d\n", p->sd, p->sb, p->fb ); */ print_planet( stdout, p->plan ); while ( /*getchar() != 'q'*/ 1 ) { printf ( "---------------------------------------------------------------------------------------\n" ); update_wator( p ); print_planet( stdout, p->plan ); printf ( "%2d) SHARKS : %2d ; \tFISH : %2d \n", ++i, p->ns, p->nf ); system("sleep 0.4"); } free_wator ( p ); return 0; }
int main(int argc, char const *argv[]) { int i; /* Variabile di scorrimento */ FILE* pianeta; /* Puntatore al pianeta da leggere */ int tp; /* Variabile che segnala se il file contenente il pianeta è stato trovato */ int pos_input; /* Variabile che segnala la posizione del file da leggere negli argomenti */ FILE* check; /* Puntatore che controlla se un parametro è un file */ int cnf; /* Contatore del numero di file apribili passati da riga di comando */ int n; /* Numero di worker */ int c; /* Numero di chronon*/ FILE* d; /* Puntatore al file su cui dumpare i risultati*/ pthread_t dtid; /* Dispatcher tid */ dispatcher dis; /* Il dispatcher */ pthread_t* ar_tid; /* Array contenente tutti i tid dei worker */ int check_create; /* Variabile di controllo sulle creazioni dei thread */ worker* arr_worker; /* Array contenente tutti i dati dei worker */ collector collettore; /* Variabile contenente i dati del collettore */ pthread_t ctid; /* Collector tid */ char* righe; char* colonne; int pfd; /* Variabile contenente la posizione del file di dump */ struct sigaction s; memset(&s, 0, sizeof(s)); s.sa_handler=gestore; if((sigaction(SIGINT,&s,NULL)) == -1) { exit(1); } if((sigaction(SIGTERM,&s,NULL)) == -1) { exit(1); } if((sigaction(SIGUSR1,&s,NULL)) == -1) { exit(1); } n = NWORK_DEF; c = CHRON_DEF; d = NULL; pfd = 0; /*Inizio il controllo dei parametri*/ if(argc <2 ) exit(1); tp = 0; if( argc%2 != 0 ) exit(1); /* Se il numero degli argomenti non è pari, esco */ cnf = 0; for(i=1; i<argc; ++i) { if( (check =fopen(argv[i], "r")) != NULL) { ++cnf; /* Controllo quanti file apribili ci sono */ fclose(check); } } if( (cnf<1) ||(cnf > 2) )exit(1); /* Se ci sono più di due file apribili, esco */ for(i=1; i<argc; ++i) /* Vado a cercare il pianeta da leggere */ { if(tp==0) /* Se non l'ho ancora trovato, continuo a cercare */ { if( (pianeta = fopen(argv[i], "r")) != NULL) { if( (strcmp(argv[i-1], "-f") != 0) ) { tp = 1; /* Ho trovato il file da leggere */ pos_input = i; } } } } if(tp==0) exit(1); /* Se non ho trovato un pianeta da leggere, esco */ for(i=1; i<argc; ++i) /* Controllo tutti gli argomenti e vedo cosa contengono*/ { if(strcmp(argv[i], "-n") == 0 ) { if(i+1>=argc) exit(1); else if ( (n = atoi(argv[i+1])) == 0) exit(1); } if(strcmp(argv[i], "-v") == 0 ) { if(i+1>=argc) exit(1); else if ( (c = atoi(argv[i+1])) == 0) exit(1); } if(strcmp(argv[i], "-f") == 0 ) /*Se l'argomento i-esimo è -f controllo il successivo*/ { if(i+1>=argc) exit(1); /*Se l'argomento successivo a -f non esiste, esco*/ else { if ( (d = fopen(argv[i+1], "w")) == NULL ) /*Se l'argomento successivo a -f non è apribile, esco*/ { exit(1); } else { pfd = i+1; /*Altrimenti incremento la posizione del file di dump*/ fclose(d); } } } } wator = new_wator((char*)argv[pos_input]); /*Alloco la matrice servito*/ servito = (int**) malloc((wator->plan->nrow)*sizeof(int*)); for(i=0; i<(wator->plan->nrow); ++i) { servito[i] = (int*) malloc((wator->plan->ncol)*sizeof(int)); } /* Alloco la matrice di lock */ mat_lock = (pthread_mutex_t*)malloc((wator->plan->nrow)*sizeof(pthread_mutex_t)); for(i=0; i<(wator->plan->nrow); ++i) { pthread_mutex_init(&mat_lock[i], NULL); } if ((pidv = fork()) !=0) { /*padre, server*/ ar_tid = (pthread_t*) malloc(n*sizeof(pthread_t)); arr_worker = (worker*) malloc(n*sizeof(worker)); /* Setto i valori iniziali per dispatcher e collector */ dis.nwork = n; dis.nrighe = wator->plan->nrow; dis.ncolonne = wator->plan->ncol; collettore.dump = d; collettore.tid = (pthread_t*) malloc(n*sizeof(pthread_t)); collettore.nwork = n; collettore.chronon = c; /* Creo il thread dispatcher*/ if( (check_create = pthread_create(&dtid, NULL, &disp, (void*) &dis)) != 0) { fclose(pianeta); free(ar_tid); free(arr_worker); free(collettore.tid); free_wator(wator); exit(1); } /* Creo i thread worker */ for(i=0; i<n; ++i) { arr_worker[i].number = i; if( (check_create = pthread_create(&ar_tid[i], NULL, &work, (void*) &arr_worker[i])) != 0 ) { fclose(pianeta); free(ar_tid); free(arr_worker); free(collettore.tid); free_wator(wator); exit(1); } collettore.tid[i] = ar_tid[i]; } /* Creo il thread collector */ if( (check_create = pthread_create(&ctid,NULL,&coll,(void*) &collettore)) != 0) { fclose(pianeta); free(ar_tid); free(arr_worker); free(collettore.tid); free_wator(wator); exit(1); } pthread_join(ctid,NULL); /* Aspetto il collector */ pthread_join(dtid, NULL); /* Aspetto il dispatcher */ /* for(i=0; i<n; ++i) { pthread_join(ar_tid[i], NULL); } */ while(wf<n); fprintf(stderr, "Ho aspettato i workers\n"); fclose(pianeta); free(ar_tid); free(arr_worker); free(collettore.tid); free(mat_lock); free(head); free(tail); for(i=0; i<(wator->plan->nrow); ++i) { free(servito[i]); } free(servito); free_wator(wator); return 0; } else { righe = (char*) malloc (16*sizeof(char)); colonne = (char*) malloc (16*sizeof(char)); sprintf(righe, "%d", wator->plan->nrow); sprintf(colonne, "%d", wator->plan->ncol); /* * Se esiste un file su cui dumpare passo il valore 1 come argomento al visualizer * e passo il nome di tale file sempre come argomento al visualizer. Nel caso non * ci sia un file su cui fare dump, passo 0 come argomento al visualizer. */ if(d != NULL) { execl("./visualizer","visualizer", righe, colonne, "1", argv[pfd], NULL); } else { execl("./visualizer","visualizer", righe, colonne, "0", NULL); } free(righe); free(colonne); return 0; } }
/*Questo è il main del processo principale, WATOR. * 1- Controllo di esistenza file * 2- Predispone i thread per la gestione corretta dei segnali * 3- Avvia i thread * 4- Aspetta che terminano il lavoro * */ int main (int argc, char *argv[]) { int n_tentativo; wat_proc_conf* x; /*Inizializzazione*/ root_thread = pthread_self(); /*Inizializza variabili globali di gestione dei segnali*/ close_all = 0; sig_sigusr1 = 0; puoi_stampare = 0; count_worker = 0; puoi_procedere = 1; n_tentativo = 0; pthread_mutex_init(&set_critica, NULL); pthread_mutex_init(&set_skip, NULL); pthread_mutex_init(&lista_mux, NULL); pthread_mutex_init(&stampa_mux, NULL); pthread_cond_init(&lista_vuota, NULL); pthread_cond_init(&stanno_lavorando, NULL); pthread_cond_init(&stampa_pronta, NULL); pthread_cond_init(&stampa_effettuata, NULL); if ( mkdir("./tmp", S_IRWXU) ) { if(errno != EEXIST) perror("Errore Creazione Directory"); } /*Rimuovo la socket se esiste, cioè se una precedente esecuzione è stata terminata male*/ system("rm -f ./tmp/*"); if( file_exist(SOCKNAME) ) { printf("Il file socket vecchio esiste ancora\n"); if( remove(SOCKNAME) ) { perror("Non è stato possibile cancellare la vecchia socket"); return 1; } } /*Gestione dei segnali * Vengono mascherati i segnali tipici di questo programma, cioè * SIGINT, SIGTERM e SIGUSR1 * L'idea è quella di mascherare i segnali a tutti i thread tranne che * al gestore dei segnali, che si preoccuperà di gestire tutto. */ sa.sa_handler=SIG_IGN; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGINT); sigaddset(&sa.sa_mask, SIGUSR2); sigaddset(&sa.sa_mask, SIGTERM); sigaddset(&sa.sa_mask, SIGUSR1); /*Applico maschera a questo thread. La maschera poi viene ereditata dai figli*/ pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL); /*Fine Gestione dei segnali*/ /*Carico gli argomenti passati al programma*/ x = valutazione_argomenti(argc, argv, NWORK_DEF, CHRON_DEF); if(x == NULL) { return 1; } /*Carico il nuovo pianeta*/ if(!file_exist(x->file)) { errno = ENOENT; perror("File planet"); return 1; } simulazione = new_wator(x->file); if(simulazione == NULL) { perror("Errore creazione nuova simulazione"); return 1; } /*Se non sono stati passati argomenti, assegno quelli di default*/ if( ( simulazione -> nwork = x->nwork ) == 0) simulazione -> nwork = NWORK_DEF; if( ( simulazione -> chronon = x->chron ) == 0) simulazione -> chronon = CHRON_DEF; if( x->dumpfile == NULL ) { strcpy(dumpfile,"stdout"); } else { strcpy(dumpfile,x->dumpfile); } intervallo_di_stampa = (x->chron) ? x->chron : CHRON_DEF; free(x->file); free(x->dumpfile); free(x); /*Creo divisione della matrici per far lavorare i thread, funzione delegata dal dispatcher*/ lista = split_matrice(simulazione->plan); /*Avvio Gestore Segnali*/ n_tentativo=0; while( start_gestore_segnali() ) { if(n_tentativo < MAX_TRY) { sleep(my_exp2(n_tentativo)); n_tentativo++; } else { perror("Errore creazione Thread Gestore Segnali"); return 1; } } /*Avvio n worker*/ n_tentativo=0; while ( (worker_thr_ids = start_nworker(simulazione->nwork)) == NULL ) { if(n_tentativo < MAX_TRY) { sleep(my_exp2(n_tentativo)); n_tentativo++; } else { perror("Errore creazione Threads NWorker"); return 1; } } /*Avvio visualizer*/ n_tentativo=0; while ( (visualizer = start_visualizer(dumpfile)) == -1 ) { if(n_tentativo < MAX_TRY) { sleep(my_exp2(n_tentativo)); n_tentativo++; } else { perror("Errore Start_Visualizer"); return 1; } } /*Avvio thread collector*/ n_tentativo=0; while( start_collector() ) { if(n_tentativo < MAX_TRY) { sleep(my_exp2(n_tentativo)); n_tentativo++; } else { perror("Errore creazione Thread Collector"); return 1; } } /*Avvio Thread Dispacer */ n_tentativo=0; while( start_dispatcher() ) { if(n_tentativo < MAX_TRY) { sleep(my_exp2(n_tentativo)); n_tentativo++; } else { perror("Errore Creazione Thread Dispatcher"); return 1; } } /*Aspetto che i thread lanciati terminano */ pthread_join(gestore_segnali_id, NULL); pthread_join(dispatcher_id, NULL); /*Procedura di recupero di collector se dormiva mentre tutti si chiudevano*/ pthread_mutex_lock(&stampa_mux); puoi_stampare = TRUE; pthread_cond_broadcast(&stampa_pronta); pthread_mutex_unlock(&stampa_mux); pthread_join(collector_id, NULL); free_wator(simulazione); free(worker_thr_ids); if( remove(SOCKNAME) ) { perror("Non è stato possibile rimuovere il file SOCKNAME"); return 1; }; pthread_mutex_destroy(&set_critica); pthread_mutex_destroy(&set_skip); pthread_mutex_destroy(&lista_mux); pthread_mutex_destroy(&stampa_mux); pthread_cond_destroy(&lista_vuota); pthread_cond_destroy(&stanno_lavorando); pthread_cond_destroy(&stampa_pronta); pthread_cond_destroy(&stampa_effettuata); return 0; }
/** * * questo programma testa tutte le funzioni finora implementate * * esegue un test alla volta passando il risultato alla funzione print_result * **/ int main () { planet_t *pl; wator_t *wt; cell_t **copia; cell_t c; int k,l,p,g,n; FILE *f1, *f2; mtrace(); print_result ( cell_to_char(WATER) == 'W' , "cell_to_char(WATER)" ); print_result ( cell_to_char(FISH) == 'F' , "cell_to_char(FISH)" ); print_result ( cell_to_char(SHARK) == 'S' , "cell_to_char(SHARK)" ); print_result ( char_to_cell('W') == WATER , "char_to_cell('W')" ); print_result ( char_to_cell('F') == FISH , "char_to_cell('F')" ); print_result ( char_to_cell('S') == SHARK , "char_to_cell('S')" ); print_result ( char_to_cell('P') == -1 , "char_to_cell('P')" ); print_result ( char_to_cell( cell_to_char (WATER) ) == WATER , "char_to_cell( cell_to_char (WATER) )" ); print_result ( cell_to_char( char_to_cell ('F') ) == 'F' , "cell_to_char( char_to_cell ('F') )" ); test_matrice_generica (10,40); test_matrice_generica (1000,40000); pl=new_planet (10,10); print_result ( ( pl!=NULL && pl->nrow==10 && pl->ncol==10 ) || errno==ENOMEM, "new_planet (10,10)" ); free_planet (pl); contatore_pesci=contatore_squali=0; print_result ( controlla_formato_e_conta_squali_e_pesci ('W', ' ', 0, &c ) && c == WATER , "controlla_formato_e_conta_squali_e_pesci ('W', ' ', 0, &c )" ); print_result ( controlla_formato_e_conta_squali_e_pesci ('F', ' ', 0, &c ) && c == FISH && contatore_pesci==1 , "controlla_formato_e_conta_squali_e_pesci ('F', ' ', 0, &c )" ); print_result ( controlla_formato_e_conta_squali_e_pesci ('S', '\n', 1, &c ) && c == SHARK && contatore_squali==1 , "controlla_formato_e_conta_squali_e_pesci ('S', '\\n', 1, &c )" ); print_result ( ! controlla_formato_e_conta_squali_e_pesci ('M', '\n', 1, &c ), "controlla_formato_e_conta_squali_e_pesci ('M', '\\n', 1, &c )" ); print_result ( ! controlla_formato_e_conta_squali_e_pesci ('W', '\n', 0, &c ), "controlla_formato_e_conta_squali_e_pesci ('W', '\\n', 0, &c )" ); print_result ( ! controlla_formato_e_conta_squali_e_pesci ('W', 'a', 0, &c ), "controlla_formato_e_conta_squali_e_pesci ('W', 'a', 0, &c )" ); print_result ( test_load_store ("custom_test/planet1.dat", 1), "test_load_store(\"custom_test/planet1.dat\")" ); print_result ( test_load_store ("custom_test/planet2.dat", 1), "test_load_store(\"custom_test/planet2.dat\")" ); print_result ( test_load_store ("custom_test/planet3.dat", 0), "test_load_store(\"custom_test/planet3.dat\")" ); print_result ( test_load_store ("custom_test/planet4.dat", 0), "test_load_store(\"custom_test/planet4.dat\")" ); print_result ( test_load_store ("custom_test/planet5.dat", 0), "test_load_store(\"custom_test/planet5.dat\")" ); wt = malloc ( sizeof(wator_t) ); wt->plan = NULL; system ("rm -f wator.conf"); print_result ( read_wator_conf (wt) == -1, "read_wator_conf without wator.conf" ); system ("cp custom_test/wator.conf.1 wator.conf"); print_result ( read_wator_conf (wt) == 1 && wt->sd == 100 && wt->sb == 20 && wt->fb == 15 , "read_wator_conf wator.conf.1" ); system ("cp custom_test/wator.conf.2 wator.conf"); print_result ( ! read_wator_conf(wt) && errno == ERANGE , "read_wator_conf wator.conf.2" ); system ("cp custom_test/wator.conf.3 wator.conf"); print_result ( ! read_wator_conf(wt) && errno == ERANGE , "read_wator_conf wator.conf.3" ); system ("cp custom_test/wator.conf.4 wator.conf"); print_result ( ! read_wator_conf(wt) && errno == ERANGE , "read_wator_conf wator.conf.4" ); system ("cp custom_test/wator.conf.5 wator.conf"); print_result ( ! read_wator_conf(wt) && errno == ERANGE , "read_wator_conf wator.conf.5" ); system ("cp custom_test/wator.conf.6 wator.conf"); print_result ( ! read_wator_conf(wt) && errno == ERANGE , "read_wator_conf wator.conf.6" ); system ("cp custom_test/wator.conf.7 wator.conf"); print_result ( ! read_wator_conf(wt) && errno == ERANGE , "read_wator_conf wator.conf.7" ); system ("cp custom_test/wator.conf.8 wator.conf"); print_result ( ! read_wator_conf(wt) && errno == ERANGE , "read_wator_conf wator.conf.8" ); free_wator (wt); system ("cp custom_test/wator.conf.1 wator.conf"); wt=new_wator ("custom_test/planet1.dat"); print_result ( wt != NULL && wt->nf == 701 && wt->ns == 300 && wt->sd == 100 && wt->sb == 20 && wt->fb == 15 && wt->plan != NULL && wt->plan->nrow == 200 && wt->plan->ncol == 130 && wt->plan->w[3][7] == SHARK , "new_wator"); k=7; l=6; print_result ( ricerca_cella (wt->plan, &k, &l, FISH) && k==7 && l==7 , "ricerca_cella (wt->pl, 7, 6, FISH)" ); k=l=0; print_result ( ricerca_cella (wt->plan, &k, &l, SHARK) && k==199 && l==0 , "ricerca_cella (wt->pl, 0, 0, SHARK)" ); k=1; l=3; print_result ( ! ricerca_cella (wt->plan, &k, &l, SHARK) && k==1 && l==3 , "ricerca_cella (wt->pl, 1, 3, SHARK)" ); k=5; l=2; print_result ( ricerca_cella (wt->plan, &k, &l, FISH) && k==5 && ( l==3 || l== 1 ), "ricerca_cella (wt->pl, 5, 2, SHARK)" ); k=20; l=25; print_result ( ricerca_cella (wt->plan, &k, &l, WATER) && ( (k==19 && l==25 ) || ( k== 20 && l== 24 ) ), "ricerca_cella (wt->pl, 20, 25, WATER)" ); print_result ( shark_rule1 ( wt, 0, 2, &k, &l ) == -1 , "shark_rule_1 (0,2)" ); print_result ( shark_rule1 ( wt, 1, 14, &k, &l ) == MOVE, "shark_rule_1 (1,15)" ); print_result ( shark_rule1 ( wt, 7, 6, &k, &l ) == EAT && k==7 && l==7, "shark_rule_1 (7,7)" ); //resetto il pianeta free_wator (wt); wt=new_wator ("custom_test/planet1.dat"); n=10; wt->plan->btime[1][14] = 3; print_result ( ! riproduzione_generica (wt->plan, 1, 14, &k, &l, 4, &n ) && k==1 && l==14 && n==10, "riproduzione_generica (wt->plan, 1, 14) - nothing" ); p=1; g=14; print_result ( riproduzione_generica (wt->plan, 1, 14, &k, &l, 4, &n ) && ricerca_cella (wt->plan, &p, &g, SHARK) && p==k && g==l && n==11, "riproduzione_generica (wt->plan, 1, 14) - born" ); wt->plan->dtime[3][7] = wt->sd; print_result ( shark_rule2 ( wt, 3, 7, &k, &l ) == DEAD && wt->plan->w[3][7] == WATER, "shark_rule2 ( wt, 3, 7) - died" ); print_result ( shark_rule2 ( wt, 7, 6, &k, &l ) == ALIVE && wt->plan->btime[7][6] == 1 , "shark_rule2 ( wt, 7, 6) - nothing" ); wt->plan->btime[7][6] = wt->sb; p=7; g=6; print_result ( shark_rule2 ( wt, 7, 6, &k, &l ) == ALIVE && ricerca_cella ( wt->plan, &p, &g, SHARK ) && p==k && g==l , "shark_rule2 ( wt, 7, 6) - born" ); //resetto il pianeta free_wator (wt); wt=new_wator ("custom_test/planet1.dat"); p=0; g=12; print_result ( fish_rule3 ( wt, 0, 12, &k, &l ) == MOVE && wt->plan->w[0][12] == WATER && ricerca_cella (wt->plan,&p,&g,FISH) && p==k && g==l , "fish_rule_3 ( wt, 0, 12) - moved" ); print_result ( ! fish_rule4 (wt, 5, 70, &k, &l ) && wt->plan->btime[5][70] == 1 , "fish_rule4 (wt, 5, 70) - nothing" ); print_result ( conta_generico ( wt->plan, FISH ) == 701 , "conta_generico ( wt->plan, FISH )" ); print_result ( conta_generico ( wt->plan, SHARK ) == 300 , "conta_generico ( wt->plan, SHARK )" ); print_result ( conta_generico ( wt->plan, WATER ) == wt->plan->ncol*wt->plan->nrow - 701 - 300 , "conta_generico ( wt->plan, WATER )" ); wt->plan->btime[5][70] = wt->fb; p=5; g=70; print_result ( ! fish_rule4 (wt, 5, 70, &k, &l ) && wt->plan->btime[5][70] == 0 && ricerca_cella (wt->plan, &p,&g,FISH) && p==k && g==l , "fish_rule4 (wt, 5, 70) - born" ); //quello in più rispetto a 701 del test di prima è appena nato. Auguri! print_result ( fish_count ( wt->plan ) == wt->nf , "fish_count ( wt->plan ) == wt->nf"); print_result ( shark_count ( wt->plan ) == wt->ns , "fish_count ( wt->plan ) == wt->ns"); //copio il pianeta e lo scrivo sul file. Poi confronto i due file, per vedere se sono uguali copia = (cell_t**) alloca_matrice_generica ( wt->plan->nrow, wt->plan->ncol, sizeof (cell_t), sizeof (cell_t *) ); copia_pianeta (copia, wt->plan->w, wt->plan->nrow, wt->plan->ncol); pl = malloc ( sizeof (planet_t) ); pl->w = copia; pl->nrow = wt->plan->nrow; pl->ncol = wt->plan->ncol; pl->btime = NULL; pl->dtime = NULL; f1 = fopen ( "custom_test/result_wt.dat", "w" ); f2 = fopen ( "custom_test/result_copia.dat", "w" ); print_planet ( f1, wt->plan ); print_planet ( f2, pl ); fclose (f1); fclose (f2); print_result ( confronto_file ( f1,f2 ), "copia_pianeta ()" ); free_wator (wt); free_planet (pl); wt = new_wator ("custom_test/planet1.dat"); free_wator (wt); muntrace(); return 0; }