/* Coordinator.java */

package philosophers;

import concurrency.Message;

/** A singleton instance of this clsss serves as the coordinator
 *
 *  @author Russell C. Bjork
 */
public class Coordinator extends Thread implements Runnable
{
    /** Accessor for the singleton instance
     *
     *  @return the singleton instance
     */
    static Coordinator getInstance()
    {
        if (theInstance == null)
        {
            theInstance = new Coordinator();
        }
        return theInstance;
    }

    /** Method required by the Runnable interface
     */
    public void run()
    {
        // Keep track of which chopsticks are in use and being waited for
        // Because of the nature of the problem, there can be at most one
        // Message representing an as yet unsatisfied request for each
        // chopstick

        boolean [] inUse = new boolean[DiningRoom.NUMBER_OF_PHILOSOPHERS];
        Message [] waitingMessages = new Message[DiningRoom.NUMBER_OF_PHILOSOPHERS];

        while(true)
        {
            // Receive a message

            Message message = Message.receive();

            // Act on it

            char request = message.getContent().charAt(0);
            int chopstick = (int) message.getContent().charAt(1);

            if (request == 'U')
            {
                if (inUse[chopstick])
                    waitingMessages[chopstick] = message;
                else
                {
                    inUse[chopstick] = true;
                    message.reply("OK");
                }
            }
            else
            {
                // If not 'U' must be 'D'

                Message waitingMessage = waitingMessages[chopstick];
                if (waitingMessage != null)
                {
                    // If there was a message waiting on this chopstick,
                    // service it

                    waitingMessages[chopstick] = null;
                    waitingMessage.reply("OK");
                }
                else
                    inUse[chopstick] = false;
            }
        }
    }

    static Coordinator theInstance;
}
