
This is a more complex example. It implements the Dining Philosophers.

If you do not know that scenario, it's simple. Philosophers sit around
a round (circular) table. Between each pair is a fork, so there is an
equal number of philosophers and forks. Philosophers think until they
become hungry, then they need both forks (the one on their left and the
one on their right side) in order to eat. Obviously, this can cause
some conflicts, because there are not enough forks for all philosophers
to eat at the same time.

The goal is to implement philosopher components that do not die from
starvation.

The classic deadlock scenario is that if philosophers are programmed to
pick up the left fork, and then to wait for the right fork to become
available, it can happen that each philosophers picks up its left fork
at the same time, so that nobody can eat.

The classic livelock scenario is that if philosophers are programmed to
drop their left fork if the right fork is not available, it can happen
that all philosophers simultaneously pick up the left fork, recognize
that the right one is not available and drop their left fork, then they
repeat the cycle. It's not a deadlock because something is happening,
but the philosophers are still starving, hence the work livelock.

Here, philosophers and forks are components, and there is an additional
component for a registration that deals out unique names to each philo-
sopher.

Philosophers have receptacles for their left and right fork, plus one
for the registration interface. They offer an attribute for polling their
status. (Ultimately, events should be sent to an observer component, but
events aren't yet implemented in MicoCCM, hence this poor-man's polling.)

The fork (or here, chopstick) throws an exception if a philosopher tries
to acquire it when already in use by another philosopher.

The philosopher overloads ccm_activate and ccm_passivate to be notified
of its activation. Upon activation, it registers with the MICO Dispatcher
to be called regularly. All the interesting work is done in this Timer
callback.

There, the philosopher becomes more hungry, then tries to aquire both
forks and eats if he has both. To prevent deadlocks, philosophers sometimes
drop one fork if they cannot get the other. To prevent livelocks, each
philosopher has its own random metabolic rate.

The client in this example is more a configurator. It contacts each home
to create the required philosopher and fork instances, and then connects
forks to the philosopher's receptacles. Once this work is done, the client
exits, and the philosophers continue to run in their server.

At the moment, all components run in a single server for simplicity. One
problem with distributing the components is that at the moment, homes are
registered in the Naming Service using their IDL name, so there can be
only one home instance of a particular type at each time.

You can start the demo by running ./philo. You may also give a number of
philosophers on the command line, the default is 3.

The client in this directory does not continue to observe the philosophers.

There is also a more fancy graphical client, `guiclient'. You can edit the
./philo shell script to run ./guiclient instead of ./client. This one con-
tinues to observe the philosopher states and displays them nicely. This
client requires Tk 8.3 and Combat (from http://www.fpx.de/Combat/).

