CLASS phil IS

 ACTIVE

pragmas

PRAGMA discriminant
        (type_name => Philosopher,
         attribute_name => --|My_ID|--)

spec

-- Dining Philosophers - Ada 95 edition
-- 
-- Philosopher is an Ada 95 task type with discriminant.
-- 
-- Michael B. Feldman, The George Washington University, July 1995.
-- HOOD version by Pierre Dissaux, TNI, June 1998.


--  required interface : 
--   Required OPERATION :
--     OPERATION : report_state of object : room
--     OPERATION : get_stick of object : room
--     OPERATION : pick_up of object : chop
--     OPERATION : put_down of object : chop
--   Required EXCEPTION : NONE
--   Required TYPE :
--     TYPE : Unique_DNA_Codes of object : society
--     TYPE : Positive of object : standard
--     TYPE : Duration of object : standard
--   Required CONSTANT : NONE
--   Required DATA : NONE

--  visibility on required modules : 
with society;
use type society.Unique_DNA_Codes;

package phil is

  task type Philosopher (My_ID : society.Unique_DNA_Codes)  is 

    entry start_eating (
      Who_Am_I : IN Society.Unique_DNA_Codes; 
      Chopstick1 : IN Positive; 
      Chopstick2 : IN Positive);
  end Philosopher;

  type Philosopher_Ptr is access all Philosopher;

  type States is (
    Breathing, Thinking, Eating, Done_Eating, 
    Got_One_Stick, Got_Other_Stick, Dying);

  procedure start_eating (
    me : IN OUT Philosopher; 
    Who_Am_I : IN Society.Unique_DNA_Codes; 
    Chopstick1 : IN Positive; 
    Chopstick2 : IN Positive);

end phil;

body

-- Dining Philosophers - Ada 95 edition
-- 
-- Philosopher is an Ada 95 task type with discriminant.
-- 
-- Michael B. Feldman, The George Washington University, July 1995.
-- HOOD version by Pierre Dissaux, TNI, June 1998.


--  visibility on required modules : 
with room;
with chop;
with Random_Generic;

--  visibility on objects required by nested operation bodies : 

package body phil is

  subtype Think_Times is Positive range 1..8;

  subtype Meal_Times is Positive range 1..10;

  subtype Life_Time is Positive range 1 .. 5;

  package Think_Length is new Random_Generic(
    Result_Subtype => Think_Times);

  package Meal_Length is new Random_Generic(
    Result_Subtype => Meal_Times);

  procedure OPCS_start_eating (
    Who_Am_I : IN Society.Unique_DNA_Codes; 
    Chopstick1 : IN Positive; 
    Chopstick2 : IN Positive) is
    Meal_Time : Meal_Times;
    Think_Time : Think_Times;
  
  begin
  
    Room.Report_State(Who_Am_I, Breathing);
  
    for Meal in Life_Time loop
  
      Room.Get_Stick(Chopstick1).all.Pick_Up;
      Room.Report_State(Who_Am_I,Got_One_Stick,Chopstick1);
  
      Room.Get_Stick(Chopstick2).all.Pick_Up;
      Room.Report_State(Who_Am_I,Got_Other_Stick,Chopstick2);
  
      Meal_Time := Meal_Length.Random_Value;
      Room.Report_State(Who_Am_I,Eating,Meal_Time,Meal);
  
      delay Duration(Meal_Time);
  
      Room.Report_State(Who_Am_I,Done_Eating);
  
      Room.Get_Stick(Chopstick1).all.Put_Down;
      Room.Get_Stick(Chopstick2).all.Put_Down;
  
      Think_Time := Think_Length.Random_Value;
      Room.Report_State(Who_Am_I,Thinking,Think_Time);
  
      delay Duration(Think_Time);
  
    end loop;
  
    Room.Report_State(Who_Am_I,Dying);
  end OPCS_start_eating;

  task body Philosopher is 


    start_eating_Who_Am_I : Society.Unique_DNA_Codes;
    start_eating_Chopstick1 : Positive;
    start_eating_Chopstick2 : Positive;
  begin
    loop
      select
        -- LSER
        accept start_eating (
          Who_Am_I : IN Society.Unique_DNA_Codes; 
          Chopstick1 : IN Positive; 
          Chopstick2 : IN Positive) do
          start_eating_Who_Am_I := Who_Am_I;
          start_eating_Chopstick1 := Chopstick1;
          start_eating_Chopstick2 := Chopstick2;
        end start_eating;
        begin
          OPCS_start_eating (start_eating_Who_Am_I, start_eating_Chopstick1, start_eating_Chopstick2 );
        exception
          when others =>
            raise;
        end;
      or
        terminate;
      end select;
    end loop;

  end Philosopher;

  procedure start_eating (
    me : IN OUT Philosopher; 
    Who_Am_I : IN Society.Unique_DNA_Codes; 
    Chopstick1 : IN Positive; 
    Chopstick2 : IN Positive) is
  begin
    me.start_eating (Who_Am_I, Chopstick1, Chopstick2 );
  end start_eating;


end phil;

END phil