A Monitor Solution for the Dining Philosophers

This is a possible solution to the dining philosophers problem using a monitor.

CONCEPT: A number of philosophers sits forever around a circular table. In the center of the table is a bowl of rice. Between each two philosophers is a shared chopstick. Each philosopher spends his/her life alternating between thinking and eating. When a philosopher gets hungry, he/she must gain exclusive access to both chopsticks before eating. We seek a mechanism that provides the necessary synchronization and meets the usual requirements of progress (efficiency), freedom from deadlock, and bounded waiting (fairness).

A monitor is used to control access to state variables and condition variables. The chopsticks themselves are not part of the monitor (nor is the rice). If they were, then the entire act of eating would have to be a monitor procedure and only one philosopher could eat at a time. Monitor procedures are defined for the actions of obtaining the chopsticks and putting them down. These are used as entry and exit protocols for program segments which actually use the chopsticks; this use takes place outside the monitor.

The number of philosophers is given by NUM_PHILS. Each philosopher can be in one of the three states THINKING, HUNGRY, or EATING. For each philosopher there is a condition variable on which that philosopher waits when he/she is hungry but one or both chopsticks are unavailable.

A philosopher who wants to eat checks the state of both neighbors and proceeds if neither is eating. Otherwise the philosopher waits. A philosopher who has finished eating gives each neighbor a chance to eat, if they are hungry and if their other chopstick is free.

MONITOR:

DATA:

	condition can_eat[NUM_PHILS];
	enum states {THINKING, HUNGRY, EATING} state[NUM_PHILS-1];
	int index;

INITIALIZATION:

	for (index=0; index<NUM_PHILS; index++) {
		flags[index] = THINKING;
	}

MONITOR PROCEDURES:

	/* request the right to pickup chopsticks and eat */
	entry void pickup(int mynum) {

		/* announce that we're hungry */
		state[mynum] = HUNGRY;

		/* if neighbor's aren't eating, proceed */
		if ((state[mynum-1 mod NUM_PHILS] != EATING) &&
			(state [mynum+1 mod NUM_PHILS] != EATING)) {
			state[mynum] = EATING;
		}

		/* otherwise wait for them */
		else can_eat[mynum].wait;

		/* ready to eat now */
		state[mynum] = EATING;
	}

	/* announce that we're finished, give others a chance */
	entry void putdown(int mynum) {

		/* announce that we're done */
		state[mynum] = THINKING;

		/* give left (lower) neighbor a chance to eat */
		if ((state [mynum-1 mod NUM_PHILS] == HUNGRY) &&
		(state [mynum-2 mod NUM_PHILS] != EATING)) {
			can_eat[mynum-1 mod NUM_PHILS].signal;
		}

		/* give right (higher) neighbor a chance to eat */
		if ((state [mynum+1 mod NUM_PHILS] == HUNGRY) &&
		(state [mynum+2 mod NUM_PHILS] != EATING)) {
			can_eat[mynum+1 mod NUM_PHILS].signal;
		}
}

PHILOSOPHER:

	/* find out our id, then repeat forever */
	me = get_my_id();
	while (TRUE) {

		/* think, wait, eat, do it all again ... */
		think();
		pickup(me);
		eat();
		putdown(me);

	}

ANALYSIS: To be added.