Another solution will be to set up a mediator that
each philosopher goes through to ask permission to use the forks. By
setting up the mediator, we are addressing the possibility of one of the
philosopher hogging to one fork for a long time while waiting for the
another fork to be released. The mediator will allow the philosopher to
take the fork only after both the forks are available. The mediator will
also allow the philosopher to use the fork based on the critical need of
it. The mediator will if for example, philosopher 1 is hungry and want
to eat so badly. Then the mediator will let philosopher 1 eat and can
also decide whether it is philosopher 3 or philosopher 4 that will eat
with philosopher 1 based on immediate need and criticality of the
philosophers. The mediator will be the judge on who needs to eat and how
long has the philosopher been waiting for the forks to eat with. This
will reduce the chance of dead lock and possible starvation.
The following is the headerfile of dining
philosopher.
/* philtable.h -- Here are the calls we can make on the monitor
* representing the dining philosophers
*/
void * tableinit(void *(*)(int *)); /* argument is the function*/
/*representing the philosopher*/
void printstate(void);
void pickup(int k);
void putdown(int k);
The following is the function dining philosopher
calls.
/* philtable.c */
#include <sys/types.h>
#include <pthread.h>
#define PHILNUM 5
typedef enum {thinking, hungry, eating} philstat;
typedef struct tablestruct {
pthread_t t[PHILNUM];
int self[PHILNUM];
pthread_mutex_t mutex;
pthread_cond_t condition[PHILNUM];
philstat status[PHILNUM];
} table;
table * tab;
void printstate(void){
/* Prints out state of philosophers as, say, TEHHE,
meaning */
/* that philosopher 0 is thinking, philosophers 1
and 4 are eating,
and*/
/* philosophers 2 and 3 are hungry.*/
static char stat[] = "THE";
int i;
for (i=0; istatus)[i]);}
printf("\n");
}
int test (int i) {
if (
((tab->status)[i] == hungry) &&
((tab->status)[(i+1)% PHILNUM] != eating)
&&
((tab->status)[(i-1+PHILNUM)% PHILNUM] !=
eating)) {
(tab->status)[i] = eating;
pthread_cond_signal(&((tab->condition)[i]));
return 1;
}
return 0;
}
void pickup(int k) {
pthread_mutex_lock(&(tab->mutex));
(tab->status)[k] = hungry;
printstate();
if (!test(k)) {
pthread_cond_wait(&((tab->condition)[k]),
&(tab->mutex));}
printstate();
pthread_mutex_unlock(&(tab->mutex));
}
void putdown(int k) {
pthread_mutex_lock(&(tab->mutex));
(tab->status)[k] = thinking;
printstate();
test((k+1)%PHILNUM);
test((k-1+PHILNUM)%PHILNUM);
pthread_mutex_unlock(&(tab->mutex));
}
table * tableinit(void *(* philosopher)(void *)) {
int i;
tab = (table *) malloc (sizeof(table));
if(pthread_mutex_init(&(tab->mutex), NULL)
!= 0) {
perror("pthread_mutex_init");
exit(1);}
for (i=0; iself)[i] = i;
(tab->status)[i] = thinking;
if(pthread_cond_init(&((tab->condition)[i]),
NULL)
!= 0) {
perror("pthread_cond_init");
exit(1);}
}
for (i=0; it)[i]),NULL,
philosopher, &((tab->self)[i]))!= 0) {
perror("pthread_create");
exit(1);}
}
return tab;
}This is the dining philosopher main file:
/* philmain.c */
#include <stdio.h>
#include "philtable.h"
void * philosopher(int * a);
int main(void) {
void * tab = tableinit(philosopher);
sleep(60); /* Wait a while then exit */
printf("WE ARE DONE\n");}
void * philosopher(int * who) {
/* For simplicity, all philosophers eat for the
same amount */
/* of time and think for a time that is simply
related */
/* to their position at the table. The parameter
who identifies */
/* the philosopher: 0, 1, 2, .. */
while (1){
sleep((*who)+1);
pickup((*who));
sleep(1);
putdown((*who));}
return who;
}