Skip to content

Instantly share code, notes, and snippets.

@pr00thmatic
Last active July 22, 2021 00:17
Show Gist options
  • Save pr00thmatic/70d0418a495b24a79a43 to your computer and use it in GitHub Desktop.
Save pr00thmatic/70d0418a495b24a79a43 to your computer and use it in GitHub Desktop.
El problema de los filósofos hambrientos (Dining Philosophers Problem). Comentado en español.
/*
Name : Dining Philosophers Problem
Author : jishnu7
Web : http://thecodecracker.com
Date : 26-Sep-2010
Description : C Program to solve Dining philosophers problem
License : GNU GPL License
Traducido al español y comentado por Vengadora.
*/
//<importando librerías>
#include <stdio.h> //printf: imprimir en salida estándar (consola)
#include <semaphore.h> //semáforos! sem_t, sem_init, ... etc ...
#include <pthread.h> //pthreads! pthread_create, ... etc ...
//</importando librerías>
//<declaración de constantes>
#define CORTO 2
#define NORMAL 3
#define LARGO 4
#define N_FILOSOFOS 5
#define PENSANDO 0
#define HAMBRIENTO 1
#define COMIENDO 2
#define IZQUIERDA ((id_fi+4)%N_FILOSOFOS)
#define DERECHA ((id_fi+1)%N_FILOSOFOS)
//</declaración de constantes>
sem_t mutex; //indica si algún filósofo está en un "proceso crítico".
/*
el proceso crítico sucede mientras algún filósofo se pone hambriento o_O
parece que los filósofos no pueden ponerse hambrientos al mismo tiempo.
Cuando a un filósofo le da hambre, todos esperan hasta que éste revise
si hay disponible un tenedor. Cuando termina de revisar, todos vuelven
a su trabajo.
*/
sem_t S[N_FILOSOFOS]; //S[i] está rojo cuando el iésimo filósofo está hambriento
//<declaración de los métodos que usaremos>...
void * ciclo_de_vida_del_filosofo(void *num);
void hambre(int);
void buen_provecho(int);
void comprobar_tenedores(int);
//</declaración de los métodos que usaremos>...
int estado[N_FILOSOFOS];
int id_fi[N_FILOSOFOS]={0, 1, 2, 3, 4};
int main()
{
int i;
pthread_t thread_id[N_FILOSOFOS]; //huh? '¬'
//iniciar el semáforo llamado "mutex" declarado en l.32
sem_init(&mutex,0,1);
for(i=0; i<N_FILOSOFOS; i++)
sem_init(&S[i],0,0); //iniciar cada uno de los semáfaros de hambre
for(i=0; i<N_FILOSOFOS; i++) { //crea a los filósofos
pthread_create(&thread_id[i], //huh? '¬'
NULL, //huh?!?! DX
ciclo_de_vida_del_filosofo, //el método que ejecutará el thread.
&id_fi[i]); //el argumento que acepta el método (puntero!!)
/*
Cada filósofo es un thread. al thread, se le envía el método que
se supone que debería ejecutar el hilo
*/
printf("El filósofo %d está pensando \n", i+1); //los filósofos nacen pensando.
}
for(i=0; i<N_FILOSOFOS; i++)
pthread_join(thread_id[i], NULL); //ponemos a todos los threads juntos o_O
}
/*
un puntero de tipo void, es una especie de genericidad primitiva.
c no tiene objetos!! pero tiene varios trucos geniales para simular
muchas propiedades de los objetos. Este es uno de ellos!
un puntero de tipo void, se puede castear a cualquier otro tipo de datos.
algo así como el "Object" de Java.
*/
// Este es el comportamiento del filósofo...
void *ciclo_de_vida_del_filosofo(void *num)
{
while(1){ //mientras el filósofo viva
int *i = num;
printf("el filósofo %d ha reiniciado su ciclo de vida!\n", *i+1);
sleep(LARGO);
hambre(*i); //le da hambre
sleep(CORTO);
buen_provecho(*i); //sacia su hambre y vuelve a pensar.
}
}
void hambre(int id_fi)
{
sem_wait(&mutex);
/*
filósofo id_fi dice:
"Esto es un proceso crítico! acaba de darme hambre y voy a
revisar los tenedores para ver si puedo comer... por favor
esperen a que yo termine de revisar los tenedores para que
ustedes puedan anunciar que están hambrientos y revisar
los tenedores.
*/
//parece que esto previene que los filósofos se mueran de hambre
//por esperar demasiado ·o·
estado[id_fi] = HAMBRIENTO; //se pone hambriento
printf("El filósofo %d tiene hambre\n", id_fi+1);
comprobar_tenedores(id_fi); //revisa los tenedores
sem_post(&mutex);
/*
mi proceso crítico acabó! sigan con sus vidas ;D
*/
sem_wait(&S[id_fi]);
/*
y ahora me pongo a comer hasta que esté saciado. Cuando esté saciado,
S[id_fi] se pondrá verde, y podré acabar este proceso.
*/
}
/*
comprueba si el filósofo puede comer
*/
void comprobar_tenedores(int id_fi)
{
if (estado[id_fi] == HAMBRIENTO && //si tengo hambre
estado[IZQUIERDA] != COMIENDO &&
/*
si el filósofo izquierdo no está comiendo quiere decir que
el tenedor izquierdo está disponible..
*/
estado[DERECHA] != COMIENDO) {
/*
si el filósofo derecho no está comiendo quiere decir que
el tenedor derecho está disponible..
*/
/*
y si todaas estas condiciones se cumplen, quiere decir que
puedo comenzar a comer! YAY! :9
*/
estado[id_fi] = COMIENDO; //me pongo a comer
sleep(NORMAL);
printf("El filósofo %d toma el tenedor %d y %d\n",
id_fi+1, IZQUIERDA+1, DERECHA+1);
sleep(CORTO);
printf("El filósofo %d está comiendo\n", id_fi+1);
sem_post(&S[id_fi]); //terminé de comer!! ^w^ (ver l.108)
}
}
/*
Cuando el filósofo deje de comer, debe poner los cubiertos en la mesa
de nuevo...
*/
void buen_provecho(int id_fi) {
sem_wait(&mutex);
printf("El filósofo %d está soltando los tendores %d y %d\n",
id_fi+1, IZQUIERDA+1, DERECHA+1);
/*
Estoy entrando en un proceso crítico! estoy desocupando los
tenedores que ocupé. por favor, nadie haga nada crítico
mientras hago esto...
*/
estado[id_fi] = PENSANDO;
printf("El filósofo %d está pensando\n", id_fi+1);
/*
barriga llena, corazón contento :3 ahora puedo volver a pensar.
*/
/*
Avisa a los filósofos que PODRÍAN necesitar los tenedores que estaba
usando, que los tenedores ya están disponibles.
*/
comprobar_tenedores(IZQUIERDA);
comprobar_tenedores(DERECHA);
/*
si los filósofos están hambrientos, prestarán atención al aviso!
de lo contrario, se irá por falso. (ver l.120)
*/
sem_post(&mutex);
/*
terminé el proceso crítico! sigan con sus vidas ^w^
*/
}
@pr00thmatic
Copy link
Author

oh, btw, el comando de compilación es:
gcc -lpthread solution.c -o solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment