/* * Problema do barbeiro dorminhoco com vários barbeiros. Glauber Módolo Cabral (RA069271) Raoni Fassina Firmino (RA069297) MO806 */ #include #include #include #include #include #define N_CLIENTES 20 #define N_BARBEIROS 3 #define N_CADEIRAS 5 sem_t sem_cadeiras; sem_t sem_cad_barbeiro[N_BARBEIROS]; sem_t sem_cabelo_cortado[N_BARBEIROS]; sem_t sem_cliente_cadeira[N_BARBEIROS]; sem_t sem_escreve_visor, sem_le_visor; int visor; /* ===== SESSÃO EXTRA INSERIDA PARA INTERFASE GRAFICA ============================= inclui declaração de variaveis e funções. */ /* MODO_VISOR: 0 -> texto(ANSI) 1 -> grafico ascii(ANSI) 2 -> grafico ascii(NCURSES) */ #include #define MODO_VISOR 2 sem_t sem_refresh; /* semafaro da função refresh */ int cadeiras_clientes [N_CADEIRAS]; /* posição dos clientes nas cadeiras de espera */ int cadeiras_barbeiros [N_BARBEIROS]; /* posição dos clientes nas cadeiras dos barbeiros */ int cadeiras_visor; /* visor dos clientes */ int entrada; /* guarda o ultimo que não conseguiu entrar */ int saida; /* guarda o ultimo que saiu da barbearia */ char * msg; /* mensagem do que esta acontecendo. */ /* funções - declaração */ int init_refresh(); int (*init_visor)(); int init_modo0(); int init_modo1(); int init_modo2(); int end_refresh(); int (*end_visor)(); int end_modo0(); int end_modo1(); int end_modo2(); int parser_refresh(int id_cliente, int id_barbeiro, int visor_id); int (*refresh_visor)(); int refresh_modo0(); int refresh_modo1(); int refresh_modo2(); /* funções - implementação */ int init_refresh() { int i; /* inicialização dos vetores de Clientes e Barbeiros como vazios */ for (i = 0; i < N_CADEIRAS; i++) cadeiras_clientes[i] = -1; for (i = 0; i < N_BARBEIROS; i++) cadeiras_barbeiros[i] = -1; /* inicialização do visor dos clientes como vazio */ cadeiras_visor = -1; /* inicia mensagem como vazia */ msg = malloc(79*sizeof(char)); /* inicializa semafaro do refresh */ sem_init(&sem_refresh, 0, 1); /* inicializa entrada e saida como vazio */ entrada = -1; saida = -1; /* inicializa funções init_visor(), end_visor() e refresh_visor() com função correspondente ao modo escolhido */ switch(MODO_VISOR) { case 0: init_visor = init_modo0; end_visor = end_modo0; refresh_visor = refresh_modo0; break; case 1: init_visor = init_modo1; end_visor = end_modo1; refresh_visor = refresh_modo1; break; case 2: init_visor = init_modo2; end_visor = end_modo2; refresh_visor = refresh_modo2; break; default: init_visor = init_modo0; end_visor = end_modo0; refresh_visor = refresh_modo0; break; } init_visor(); return 0; } int init_modo0() { return 0; } int init_modo1() { return 0; } int init_modo2() { initscr(); start_color(); curs_set(0); init_pair(1,COLOR_WHITE,COLOR_BLUE); /* cor de fundo e padrão */ init_pair(2,COLOR_RED,COLOR_BLACK); /* cor do visor */ init_pair(3,COLOR_WHITE,COLOR_BLACK); /* cor das cadeiras dos clientes */ init_pair(4,COLOR_WHITE,COLOR_GREEN); /* cor de barbeiro livre */ init_pair(5,COLOR_WHITE,COLOR_YELLOW); /* cor de barbeiro dormindo */ init_pair(6,COLOR_WHITE,COLOR_RED); /* cor de barbeio ocupado */ /*Imprimindo parte estatica do cenario*/ bkgd(COLOR_PAIR(1)); attron(COLOR_PAIR(2)); mvprintw(0,0," Action: "); mvprintw(1,0," "); mvprintw(14,0," "); mvprintw(18,3,"XX"); attroff(COLOR_PAIR(2)); attron(COLOR_PAIR(3)); mvprintw(21,3,"XX"); attroff(COLOR_PAIR(3)); attron(COLOR_PAIR(4)); mvprintw(21,43,"XX"); mvprintw(23,3,"XX"); attroff(COLOR_PAIR(4)); attron(COLOR_PAIR(5)); mvprintw(22,43,"XX"); attroff(COLOR_PAIR(5)); attron(COLOR_PAIR(6)); mvprintw(23,43,"XX"); mvprintw(22,3,"XX"); attroff(COLOR_PAIR(6)); mvprintw(16,1,"Legenda:"); mvprintw(20,3,"Cliente"); mvprintw(21,6,"Cadeira ocupada pelo cliente XX"); mvprintw(22,6,"Cliente XX que não entrou"); mvprintw(23,6,"Cliente XX que acabou de sair"); mvprintw(18,6,"Visor mostrando barbeiro XX disponivel"); mvprintw(20,43,"Barbeiro"); mvprintw(21,46,"Barbeiro XX Disponivel"); mvprintw(22,46,"Barbeiro XX Dormindo"); mvprintw(23,46,"Barbeiro XX Ocupado"); refresh_modo2(); return 0; } int end_refresh() { end_visor(); return 0; } int end_modo0() { return 0; } int end_modo1() { return 0; } int end_modo2() { endwin(); return 0; } /* Refresh: Segue o esquema do valor de MODO_VISOR. define id >= 0; define visor >= 0; Entradas: id_cliente = (-1 | id); id_barbeiro = (-1 | id); visor_id = (-1 | id); funcionamento: _ significa, se visor_id = id, mostra o valor do visor, se igual a -1, mostra "OCUPADO". f_refresh (-1, -1, _ ) --> Refresh sem alterações. f_refresh (id, -1, _ ) --> Refresh entra Cliente. f_refresh (id, id, _ ) --> Refresh cliente sai da espera e vai para a cadeira do barbeiro. f_refresh (-1, id, _ ) --> Refresh barbeiro termina o corte, cliente vai embora, barbeiro dorme. */ int parser_refresh(int id_cliente, int id_barbeiro, int visor_id) { int i; /* trava a função refresh */ /*sem_wait(&sem_refresh);*/ entrada = -1; saida = -1; /* entrada se ID do cliente e ID visor, ID visor para distinguir dos dois casos que é só ID cliente. Significa Cliente não entrou. */ if (id_cliente > -1 && id_barbeiro == -1 && visor_id > -1) { entrada = id_cliente; snprintf(msg,79,"Cliente %d não entrou na barbearia.", id_cliente); refresh_visor(); return sem_post(&sem_refresh); } /* entrada se ID do cliente, entrou na barbearia ou saiu da barbearia */ if (id_cliente > -1 && id_barbeiro == -1 && visor_id == -1) { /* se cliente esta na cadeira de barbeiro então saiu da barbearia */ for (i = 0; i < N_BARBEIROS; i++) { if (cadeiras_barbeiros[i] == id_cliente) { cadeiras_barbeiros[i] = -1; saida = id_cliente; snprintf(msg,79,"Cliente %d deixou a barbearia.", id_cliente); refresh_visor(); return sem_post(&sem_refresh); } } /* se a fila não esta cheia, então cliente entrou */ for (i = 0; i < N_CADEIRAS; i++) { if (cadeiras_clientes[i] == -1) { cadeiras_clientes[i] = id_cliente; snprintf(msg,79,"Cliente %d entrou na barbearia.", id_cliente); refresh_visor(); return sem_post(&sem_refresh); } } } /* entrada todas as IDs e Visor, unica situação, cliente vai para a cadeira do barbeiro */ if (id_cliente > -1 && id_barbeiro > -1 && visor_id > -1) { for (i = 0; i < N_CADEIRAS; i++) { if (cadeiras_clientes[i] == id_cliente) { cadeiras_clientes[i] = -1; cadeiras_barbeiros[id_barbeiro] = id_cliente; cadeiras_visor = -1; snprintf(msg,79,"Cliente %d sentou na cadeira do barbeiro %d.", id_cliente, id_barbeiro); refresh_visor(); return sem_post(&sem_refresh); } } } /* entrada se visor_ID, barbeiro acorda e marca o visor */ if (id_cliente == -1 && id_barbeiro == -1 && visor_id > -1) { cadeiras_visor = visor_id; snprintf(msg,79,"Barbeiro %d disponivel.", visor_id); refresh_visor(); return sem_post(&sem_refresh); } /* entrada se ID_barbeiro, barbeiro termina de cortar cabelo e espera cliente sair. Só atualiza quando há clientes na cadeira. */ if (id_cliente == -1 && id_barbeiro > -1 && visor_id == -1) /* if (id_cliente == -1 && cadeiras_barbeiros[id_barbeiro] !=-1 && id_barbeiro > -1 && visor_id == -1) */ { snprintf(msg,79,"Barbeiro %d cortou o cabelo do cliente %d.", id_barbeiro, cadeiras_barbeiros[id_barbeiro]); refresh_visor(); return sem_post(&sem_refresh); } /*Refresh*/ refresh_visor(); /* livra a função refresh */ return sem_post(&sem_refresh); } int refresh_modo0() { printf("%s\n",msg); return 0; } int refresh_modo1() { int i; printf("\n________________________________________________________________________________\n"); printf("%s\n",msg); printf("\n--------------------------------------------------------------------------------\n"); printf("CLIENTES:\n"); for (i = 0; i < N_CADEIRAS; i++) { if (cadeiras_clientes[i] > -1 && cadeiras_clientes[i] < 10) printf(" "); printf("%d ", cadeiras_clientes[i]); } printf("\n"); for (i = 0; i < N_CADEIRAS; i++) { printf("-- "); } printf("\n\nVISOR: "); if (cadeiras_visor > -1) printf("%d", cadeiras_visor); else printf("OCUPADO"); printf("\n\nBARBEIROS:\n"); for (i = 0; i < N_BARBEIROS; i++) { if (cadeiras_barbeiros[i] > -1 && cadeiras_barbeiros[i] < 10) printf(" "); printf("%d ", cadeiras_barbeiros[i]); } printf("\n"); for (i = 0; i < N_BARBEIROS; i++) { printf("-- "); } printf("\n"); for (i = 0; i < N_BARBEIROS; i++) { if (i < 10) printf(" "); printf("%d ",i); } printf("\n--------------------------------------------------------------------------------\n"); return 0; } int refresh_modo2() { int i; int posc, posb; int bcolor; posc = 41 - (N_CADEIRAS/2.0)*4; posb = 41 - (N_BARBEIROS/2.0)*4; /* imprime cadeiras dos clientes */ attron(COLOR_PAIR(3)); for (i = 0; i < N_CADEIRAS; i++) { move(4,posc+i*4); if (cadeiras_clientes[i] < 10) printw(" "); if (cadeiras_clientes[i] == -1) printw(" "); else printw("%d", cadeiras_clientes[i]); } attroff(COLOR_PAIR(3)); /* imprime caideras dos barbeiros e barbeiros */ for (i = 0; i < N_BARBEIROS; i++) { /* imprime a cadeira do barbeiro */ attron(COLOR_PAIR(3)); move(10,posb+i*4); if (cadeiras_barbeiros[i] < 10) printw(" "); if (cadeiras_barbeiros[i] == -1) printw(" "); else printw("%d", cadeiras_barbeiros[i]); attroff(COLOR_PAIR(3)); /* escolhe cor/estado do barbeiro */ if (cadeiras_visor == i) bcolor = 4; /* cor livre, verde */ else { if (cadeiras_barbeiros[i] == -1) bcolor = 5; /* cor dormindo, amarelo */ else bcolor = 6; /* cor ocupado, vermelho */ } /* imprime o barbeiro */ attron(COLOR_PAIR(bcolor)); move(11,posb+i*4); if (i < 10) printw(" "); printw("%d",i); attroff(COLOR_PAIR(bcolor)); } /* imprime visor */ attron(COLOR_PAIR(2)); mvprintw(6,38," "); mvprintw(7,38," "); mvprintw(8,38," "); move(7,39); if (cadeiras_visor == -1) printw("XX"); else { if(cadeiras_visor < 10) printw("0"); printw("%d",cadeiras_visor); } attroff(COLOR_PAIR(2)); /* imprime entrada e saida */ attron(COLOR_PAIR(6)); move(4, posc-4); if (entrada < 10) printw(" "); if (entrada == -1) printw(" "); else printw("%d",entrada); attroff(COLOR_PAIR(6)); attron(COLOR_PAIR(4)); move(4,posc + 4*N_CADEIRAS); if (saida < 10) printw(" "); if (saida == -1) printw(" "); else printw("%d",saida); attroff(COLOR_PAIR(4)); attron(COLOR_PAIR(3)); mvprintw(1,1," "); mvprintw(1,1,"%s",msg); attroff(COLOR_PAIR(3)); refresh(); sleep(1); return 0; } /* ===== FINAL SESSÃO EXTRA ======================================================= */ void* f_barbeiro(void *v) { int id = *(int*)v; while(1) { sem_wait(&sem_escreve_visor); visor = id; sem_wait(&sem_refresh); parser_refresh(-1,-1,visor); /* REFRESH */ sem_post(&sem_le_visor); sem_wait(&sem_cliente_cadeira[id]); /*printf("Barbeiro %d cortou o cabelo de um cliente.\n", id);*/ sem_wait(&sem_refresh); parser_refresh(-1,id,-1); /* REFRESH */ sem_post(&sem_cabelo_cortado[id]); sleep(random()%3); } return NULL; } void* f_cliente(void* v) { int id = *(int*) v; int minha_cadeira; sleep(random()%3+1); if (sem_trywait(&sem_cadeiras) == 0) { /*printf("Cliente %d entrou na barbearia.\n", id);*/ sem_wait(&sem_refresh); parser_refresh(id,-1,-1); /* REFRESH */ sem_wait(&sem_le_visor); minha_cadeira = visor; /* REFRESH -- mesmo que o de baixo ???*/ sem_post(&sem_escreve_visor); sem_wait(&sem_cad_barbeiro[minha_cadeira]); /*printf("Cliente %d sentou na cadeira do barbeiro %d.\n", id, minha_cadeira);*/ sem_wait(&sem_refresh); parser_refresh(id,minha_cadeira,minha_cadeira); /* REFRESH */ sem_post(&sem_cliente_cadeira[minha_cadeira]); sem_post(&sem_cadeiras); sem_wait(&sem_cabelo_cortado[minha_cadeira]); /*printf("Cliente %d deixou a barbearia.\n", id);*/ sem_wait(&sem_refresh); parser_refresh(id,-1,-1); /* REFRESH */ sem_post(&sem_cad_barbeiro[minha_cadeira]); /* printf("Cliente %d deixou a barbearia.\n", id); -- posição errada do printf, movido linha acima */ } else { /*printf("Cliente %d não entrou na barbearia.\n", id);*/ sem_wait(&sem_refresh); parser_refresh(id,-1,id); /* REFRESH */ } return NULL; } int main() { pthread_t thr_clientes[N_CLIENTES], thr_barbeiros[N_BARBEIROS]; int i, id_cl[N_CLIENTES], id_bar[N_BARBEIROS]; sem_init(&sem_cadeiras, 0, N_CADEIRAS); /* mudança de 5 para N_CADEIRAS, deixar genérico o código */ sem_init(&sem_escreve_visor, 0, 1); sem_init(&sem_le_visor, 0, 0); init_refresh(); /* linha adicionada ao main(), inicialização do refresh */ for (i = 0; i < N_BARBEIROS; i++) { sem_init(&sem_cad_barbeiro[i], 0, 1); sem_init(&sem_cliente_cadeira[i], 0, 0); sem_init(&sem_cabelo_cortado[i], 0, 0); } for (i = 0; i < N_CLIENTES; i++) { id_cl[i] = i; pthread_create(&thr_clientes[i], NULL, f_cliente, (void*) &id_cl[i]); } for (i = 0; i < N_BARBEIROS; i++) { id_bar[i] = i; pthread_create(&thr_barbeiros[i], NULL, f_barbeiro, (void*) &id_bar[i]); } for (i = 0; i < N_CLIENTES; i++) pthread_join(thr_clientes[i], NULL); /* Barbeiros são assassinados */ getch(); end_refresh(); /* linha adicionada ao main(), finalização do refresh */ return 0; }