/** * Implementação assimétrica do jantar dos filósofos, utilizando ncurses. * * @author Crístian Viana (cristian.viana@students.ic.unicamp.br) * @author Priscila Saboia (priscila.saboia@students.ic.unicamp.br) */ #include #include #include #include #include #include #define N_CICLOS 8 sem_t sem_garfo[5]; sem_t sem_mesa; enum estado_filosofo {PENSANDO = 'T', COM_FOME = 'H', COMENDO = 'E'}; struct localizacao_t { int x; int y; }; struct garfo_t { struct localizacao_t l9o; /* 'l' + strlen("ocalizaca") + 'o' */ char forma; }; /* localização dos filósofos */ struct localizacao_t filosofos[5] = { {2, 5}, {2, 9}, {3, 12}, {4, 7}, {3, 2} }; /* localização e forma dos garfos */ struct garfo_t garfos[5] = { {{2, 3}, '\\'}, {{2, 7}, '|'}, {{2, 11}, '/'}, {{4, 11}, '\\'}, {{4, 3}, '/'} }; /** * Altera o estado de um filósofo. * * @param phil_id O ID do filósofo. * @param e O novo estado do filósofo. */ void alterar_filosofo(int phil_id, enum estado_filosofo e) { int attr = COLOR_PAIR(phil_id + 1); if (e == COMENDO) { attr |= A_STANDOUT; } mvaddch(filosofos[phil_id].x, filosofos[phil_id].y, (char) e | attr); } /** * Altera a cor de um garfo. * * @param phil_id O ID do garfo. * @param cor A nova cor do garfo. */ void alterar_garfo(int gid, int cor) { mvaddch(garfos[gid].l9o.x, garfos[gid].l9o.y, garfos[gid].forma | cor); } /** * Atualiza a tela, deixando o cursor embaixo da cena dos filósofos. */ void atualizar() { move(5, 0); /* só pra colocar o cursor fora dos filósofos */ refresh(); } /** * Executa as funções de inicialização e desenha a cena inicial dos filósofos. */ void inicializar() { int i; /* inicialização do ncurses */ initscr(); /* inicialização das cores */ start_color(); init_pair(1, COLOR_RED, COLOR_BLACK); /* filósofo 0 */ init_pair(2, COLOR_GREEN, COLOR_BLACK); /* filósofo 1 */ init_pair(3, COLOR_YELLOW, COLOR_BLACK); /* filósofo 2 */ init_pair(4, COLOR_BLUE, COLOR_BLACK); /* filósofo 3 */ init_pair(5, COLOR_MAGENTA, COLOR_BLACK); /* filósofo 4 */ init_pair(6, COLOR_WHITE, COLOR_BLACK); /* garfo sem filósofo */ /* escrever o título, em negrito */ attron(A_BOLD | A_UNDERLINE); addstr("*** FILÓSOFOS FAMINTOS ***"); attroff(A_BOLD | A_UNDERLINE); /* escrever a disposição inicial dos filósofos. no início, eles estão pensando. */ for (i = 0; i < 5; i++) { alterar_filosofo(i, PENSANDO); alterar_garfo(i, COLOR_PAIR(6)); } atualizar(); } /** * Executa as rotinas de finalização. */ void finalizar() { /* finalização do ncurses */ endwin(); } void fica_com_fome(int phil_id) { sem_wait(&sem_mesa); alterar_filosofo(phil_id, COM_FOME); atualizar(); sem_post(&sem_mesa); sleep(1); } void come(int phil_id) { sem_wait(&sem_mesa); alterar_filosofo(phil_id, COMENDO); atualizar(); sem_post(&sem_mesa); sleep(1); } void pega_garfo_esq(int phil_id) { int esq = (phil_id + 1) % 5; sem_wait(&sem_garfo[esq]); sem_wait(&sem_mesa); alterar_garfo(esq, COLOR_PAIR(phil_id + 1)); atualizar(); sem_post(&sem_mesa); sleep(1); } void pega_garfo_dir(int phil_id) { sem_wait(&sem_garfo[phil_id]); sem_wait(&sem_mesa); alterar_garfo(phil_id, COLOR_PAIR(phil_id + 1)); atualizar(); sem_post(&sem_mesa); sleep(1); } void solta_garfos_pensa(int phil_id) { int esq = (phil_id + 1) % 5; sem_wait(&sem_mesa); sem_post(&sem_garfo[esq]); sem_post(&sem_garfo[phil_id]); alterar_filosofo(phil_id, PENSANDO); alterar_garfo(esq, COLOR_PAIR(6)); alterar_garfo(phil_id, COLOR_PAIR(6)); atualizar(); sem_post(&sem_mesa); sleep(1); } void *f_phil(void *v) { int phil_id = *(int *) v; int i; for (i = 0; i < N_CICLOS; i++) { fica_com_fome(phil_id); if (phil_id % 2) { pega_garfo_dir(phil_id); pega_garfo_esq(phil_id); } else { pega_garfo_esq(phil_id); pega_garfo_dir(phil_id); } come(phil_id); solta_garfos_pensa(phil_id); } return NULL; } int main() { pthread_t thr[5]; int i, phil_id[5]; inicializar(); sem_init(&sem_mesa, 0, 1); for (i = 0; i < 5; i++) { sem_init(&sem_garfo[i], 0, 1); } for (i = 0; i < 5; i++) { phil_id[i] = i; pthread_create(&thr[i], NULL, f_phil, &phil_id[i]); } for (i = 0; i < 5; i++) { pthread_join(thr[i], NULL); } for (i = 0; i < 5; i++) { sem_destroy(&sem_garfo[i]); } sem_destroy(&sem_mesa); finalizar(); return 0; }