OBJECT room IS

 ACTIVE

DESCRIPTION

PROBLEM

Statement of the Problem (text)

Room manages the simulation:
- intanciates Philosophers and Sticks.
- assigns each Philosopher a seat and his chopsticks.
- creates windows on the screen.
- displays information dynamically inside each window.(cf.FR3/Report_events:)

Referenced Documents (text)

This application is the HOOD version of "Dining Philosophers - Ada95 edition" from Michael B. Feldman, The George Washington University, July 1995.
HOOD adaptation was performed by Pierre Dissaux, TNI, June 1998, with STOOD toolset.

Analysis of Requirements

Structural Requirements (text)

Room must manage:
SR1: dining room seats (cf.SR1/Dining_room_seats:)
SR2: Philosophers (cf.SR2/Philosophers:)
SR3: chopsticks (cf.SR3/Chopsticks:)
SR4: display windows (cf.SR4/Display_windows:)
SR5: simulation timing (cf.SR5/Simulation_timing:)

Functionnal Requirements (text)

Room provides thre functional services:
FR1: prepare and begin the diner. (cf.FR1/Prepare&begin_diner:)
FR2: provide chopsticks to Philosophers. (cf.FR2/Provide_chopsticks:)
FR3: report events to outside world. (cf.FR3/Report_events:)

Behavioural Requirements (text)

Dining room behaviour should be as follow:
BR3: start diner asynchronously (cf.BR3/Dynamic_events_report:)
BR4: report event synchronously (cf.BR4/Synchronous_events_report:)
BR5: Dining room has two possible states (Waiting or Dining) (cf.BR5/Dining_room_states:)

Local Environment

Parent General Description (text)

Please refer to parent module description.

SOLUTION

General Strategy (text)

Dining room is designed as an active HOOD4 object, as it must have its own control flow.
Structural element (types, constants and data) are all hidden inside internal part.
Behaviour is described by a HOOD4 STD (State Transtion Diagram) and constraints on provided operations, and encapsulated inside a HOOD OBCS (Object Control Structure).
Implementation of functional services are descibed directly inside HOOD OPCSs (Operation Control Structures).

Code generator will produce a package containing a task called OBCS.
(cf.BR5/Dining_room_states:)

Structural Description

Identification of Data Structures (text)

Structural elements are all hidden inside internals of this module, as none of them is required from outside.
They are listed below:

SR1:
- type Table_Type describes the table.
- constant Table_Size specifies the size of the table (5 seats).
- data Phil_Seats is used to allocate a seat to each Philosopher.
SR2: 
- data P1 to P5 are five instances of Phil.Philosopher.
- data Phils is an array of pointers on these Philosophers.
SR3:
- data S1 to S5 are five instances of Chop.Stick.
- data Sticks is an array of pointers on these chopsticks.
SR4:
- data Phil_Windows is an array of five Windows.window.
SR5:
- data Start_Time is initialized when simulation starts.
- data T provides current simulation time.

Functional Description

Identification of Operations (text)

Operations provided by dining room are:

FR1: 
Start_Serving: sets up the table and start the diner. 
It is called by main procedure of the program.
FR2: 
Get_Stick: implements the request from a Philosopher to pick up a chopstick.
This procedure didn't exist inside original Ada code where chopsticks were declared as public data, and were thus directly visible from Phil module. Provided data being forbidden when designing with HOOD, chopstick instances were declared within the internals, and Get_Stick access function was added to implement remote requests.
FR3:
Report_State: is used by Philosophers to indicate in which internal state they are.

Grouping Operations (text)

None.

Behavioural Description

Identification of Local Behaviour (text)

Dining room behaviour is represented by a State Transition model and constraints on operation execution requests:

BR5: Dining room has two distinct states:
- waiting state, identified by internal state variable "started" set to FALSE, where Room may only receive "Start_Serving" execution requests.
- dining state, identified by internal state variable "started" set to TRUE, where Room may only receive "Report_State" execution requests.

BR3: Start_Serving has an asynchronous execution request (ASER).

BR4: Report_State has a highly synchronous execution request (HSER), so that Philosopher 's internal state doesn't change while current state is displayed on relevant window.

Justification of Design Decisions (text)

A few changes in initial source code were required to fit HOOD4 design rules:
- Sticks variable was initially declared within package spec, which is forbidden with HOOD, so it was moved into package body, and an additional access function (Get_Stick) may be used to pick_up on one of the five chopsticks.
- As chopsticks are instances of a  protected type, which is thus a limited type, they cannot be returned directly by an access function. Sticks thus became an array of pointers on chopsticks.
- To comply with standard HOOD code generation rules, task entries are not directly called from outside. Remote clients should call Room.Start_Serving and Room.Report_State which remame task entries of the same name. For the same reason, relevant bodies are implemented into additional internal OPCS_Start_serving and OPCS_Report_State procedures.
- Within original code, main control task was called "Maitre_D". Its name become "OBCS" when generated from a HOOD design. Task body is also automatically generated from STD and operation constraints: this implies changes to code structure.

PROVIDED_INTERFACE

OPERATIONS

start_serving

operation spec. description (text)

Room.Start_Serving is called by main procedure and renames OBCS.Start_Serving task entry.
This procedure has no parameter. 
(cf.FR1/Prepare&begin_diner:)

operation declaration (hood)

start_serving;

real time attributes (hood)

WCET

report_state

operation spec. description (text)

Room.Report_State is called by Phil.Start_Eating and renames OBCS.Report_State task entry.
This procedure has four parameters:
- Which_Phil: identifies actual Philosopher sending the message.
- State: current state of sender.
- How_Long: length of current state (or identifier of used chopstick).
- Which_Meal: current meal.
(cf.FR3/Report_events:)

operation declaration (hood)

report_state(
        Which_Phil : in Society.Unique_DNA_Codes;
        Which_State : in Phil.States;
        How_Long : in Natural := --|0|--;
        Which_Meal : in Natural := --|0|--
);

real time attributes (hood)

WCET

get_stick

operation spec. description (text)

Room.Get_Stick is an access function to internal Sticks variable.
It requires a chopstick ID (Which_Stick) to return a pointer to relevant protected object.
(cf.FR2/Provide_chopsticks:)

operation declaration (hood)

get_stick(which_Stick : in Positive) return Chop.Stick_Ptr;

real time attributes (hood)

WCET

OBJECT_CONTROL_STRUCTURE

obcs spec. description (text)

A dedicated state variable manages current state of dining room.
This variable "Started" has a default value of "FALSE" and become "TRUE" after Start_Serving has been executed.
Start_Serving and Report_State have both STATE and protocole constraints.

constrained operations

start_serving CONSTRAINED_BY ASER STATE;
report_state CONSTRAINED_BY HSER STATE;

REQUIRED_INTERFACE

OBJECT calendar;

        TYPES

                Time;

        CONSTANTS

                NONE

        OPERATION_SETS

                NONE

        OPERATIONS

                Clock;

        EXCEPTIONS

                NONE

OBJECT chop;

        TYPES

                Stick_Ptr; Stick;

        CONSTANTS

                NONE

        OPERATION_SETS

                NONE

        OPERATIONS

                NONE

        EXCEPTIONS

                NONE

OBJECT phil;

        TYPES

                States; Philosopher; Philosopher_Ptr;

        CONSTANTS

                NONE

        OPERATION_SETS

                NONE

        OPERATIONS

                start_eating;

        EXCEPTIONS

                NONE

OBJECT society;

        TYPES

                Unique_DNA_Codes;

        CONSTANTS

                NONE

        OPERATION_SETS

                NONE

        OPERATIONS

                get_name;

        EXCEPTIONS

                NONE

OBJECT standard;

        TYPES

                Natural; Integer; Positive; Boolean;

        CONSTANTS

                NONE

        OPERATION_SETS

                NONE

        OPERATIONS

                NONE

        EXCEPTIONS

                NONE

OBJECT windows;

        TYPES

                Window;

        CONSTANTS

                NONE

        OPERATION_SETS

                NONE

        OPERATIONS

                open; borders; title; put#1; new_line;

        EXCEPTIONS

                NONE

DATAFLOWS

starting => phil;
displaying => windows;

INTERNALS

TYPES

Table_Type

type description (text)

Identifies the possible locations around the table.

type attributes (hood)

ATTRIBUTES NONE

type enumeration (hood)

ENUMERATION NONE

type definition (ada)

subtype Table_Type is Positive range 1..Table_Size;

CONSTANTS

Table_Size

constant description (text)

Specifies the total number of seats around the table. It is limited to five in this example.

constant definition (ada)

Table_Size : constant := 5;

DATA

S1

data description (text)

First chopstick shared between seats 5 and 1.

data declaration (ada)

S1 : aliased Chop.Stick;

data access from pseudo_code

(da) room.S1 IS USED BY NONE

data access from Ada code

(da) room.S1 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.S1 IS USED BY NONE

data access from C++ code

(da) room.S1 IS USED BY NONE

S2

data description (text)

second chopstick shared between seats 1 and 2.

data declaration (ada)

S2 : aliased Chop.Stick;

data access from pseudo_code

(da) room.S2 IS USED BY NONE

data access from Ada code

(da) room.S2 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.S2 IS USED BY NONE

data access from C++ code

(da) room.S2 IS USED BY NONE

S3

data description (text)

Third chopstick shared between seats 2 and 3.

data declaration (ada)

S3 : aliased Chop.Stick;

data access from pseudo_code

(da) room.S3 IS USED BY NONE

data access from Ada code

(da) room.S3 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.S3 IS USED BY NONE

data access from C++ code

(da) room.S3 IS USED BY NONE

S4

data description (text)

Fourth chopstick shared between seats 3 and 4.

data declaration (ada)

S4 : aliased Chop.Stick;

data access from pseudo_code

(da) room.S4 IS USED BY NONE

data access from Ada code

(da) room.S4 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.S4 IS USED BY NONE

data access from C++ code

(da) room.S4 IS USED BY NONE

S5

data description (text)

Fifth chopstick shared between seats 4 and 5.

data declaration (ada)

S5 : aliased Chop.Stick;

data access from pseudo_code

(da) room.S5 IS USED BY NONE

data access from Ada code

(da) room.S5 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.S5 IS USED BY NONE

data access from C++ code

(da) room.S5 IS USED BY NONE

Sticks

data description (text)

An array of pointers to the chopsticks.

data declaration (ada)

Sticks : array (Table_Type) of Chop.Stick_Ptr;

data access from pseudo_code

(da) room.Sticks IS USED BY NONE

data access from Ada code

(da) room.Sticks IS USED BY 
        (op) room.get_stick [R]
        (op) room.start_serving [R]

data access from C code

(da) room.Sticks IS USED BY NONE

data access from C++ code

(da) room.Sticks IS USED BY NONE

P1

data description (text)

First Philosopher.

data declaration (ada)

P1 : aliased Phil.Philosopher(My_ID => 1);

data access from pseudo_code

(da) room.P1 IS USED BY NONE

data access from Ada code

(da) room.P1 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.P1 IS USED BY NONE

data access from C++ code

(da) room.P1 IS USED BY NONE

P2

data description (text)

Second Philosopher.

data declaration (ada)

P2 : aliased Phil.Philosopher(My_ID => 2);

data access from pseudo_code

(da) room.P2 IS USED BY NONE

data access from Ada code

(da) room.P2 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.P2 IS USED BY NONE

data access from C++ code

(da) room.P2 IS USED BY NONE

P3

data description (text)

Third Philosopher.

data declaration (ada)

P3 : aliased Phil.Philosopher(My_ID => 3);

data access from pseudo_code

(da) room.P3 IS USED BY NONE

data access from Ada code

(da) room.P3 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.P3 IS USED BY NONE

data access from C++ code

(da) room.P3 IS USED BY NONE

P4

data description (text)

Fourth Philosopher.

data declaration (ada)

P4 : aliased Phil.Philosopher(My_ID => 4);

data access from pseudo_code

(da) room.P4 IS USED BY NONE

data access from Ada code

(da) room.P4 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.P4 IS USED BY NONE

data access from C++ code

(da) room.P4 IS USED BY NONE

P5

data description (text)

Fifth Philosopher.

data declaration (ada)

P5 : aliased Phil.Philosopher(My_ID => 5);

data access from pseudo_code

(da) room.P5 IS USED BY NONE

data access from Ada code

(da) room.P5 IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.P5 IS USED BY NONE

data access from C++ code

(da) room.P5 IS USED BY NONE

Phils

data description (text)

An array of pointers to the Philosophers.

data declaration (ada)

Phils : array (Table_Type) of Phil.Philosopher_Ptr;

data access from pseudo_code

(da) room.Phils IS USED BY NONE

data access from Ada code

(da) room.Phils IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.Phils IS USED BY NONE

data access from C++ code

(da) room.Phils IS USED BY NONE

Phil_Windows

data description (text)

An array of windows. One window for each seat.

data declaration (ada)

Phil_Windows : array (Table_Type) of Windows.Window;

data access from pseudo_code

(da) room.Phil_Windows IS USED BY NONE

data access from Ada code

(da) room.Phil_Windows IS USED BY 
        (op) room.report_state [R]
        (op) room.start_serving [R]

data access from C code

(da) room.Phil_Windows IS USED BY NONE

data access from C++ code

(da) room.Phil_Windows IS USED BY NONE

Phil_Seats

data description (text)

An array to indicate which seat each Philosopher occupies:
Philosopher 1 occupies seat 1;
Philosopher 2 occupies seat 3;
Philosopher 3 occupies seat 5;
Philosopher 4 occupies seat 4;
Philosopher 5 occupies seat 2;

data declaration (ada)

Phil_Seats : array (Society.Unique_DNA_Codes) of Table_Type;

data access from pseudo_code

(da) room.Phil_Seats IS USED BY NONE

data access from Ada code

(da) room.Phil_Seats IS USED BY 
        (op) room.report_state [R]
        (op) room.start_serving [R]

data access from C code

(da) room.Phil_Seats IS USED BY NONE

data access from C++ code

(da) room.Phil_Seats IS USED BY NONE

T

data description (text)

Current time obtained by Calendar.Clock.

data declaration (ada)

T : Natural;

data access from pseudo_code

(da) room.T IS USED BY NONE

data access from Ada code

(da) room.T IS USED BY 
        (op) room.report_state [R]

data access from C code

(da) room.T IS USED BY NONE

data access from C++ code

(da) room.T IS USED BY NONE

Start_Time

data description (text)

Time when application is launched.

data declaration (ada)

Start_Time : Calendar.Time;

data access from pseudo_code

(da) room.Start_Time IS USED BY NONE

data access from Ada code

(da) room.Start_Time IS USED BY 
        (op) room.report_state [R]
        (op) room.start_serving [R]

data access from C code

(da) room.Start_Time IS USED BY NONE

data access from C++ code

(da) room.Start_Time IS USED BY NONE

Started

data description (text)

State variable to switch between "waiting" and "dining" states.
Initial state is "Waiting".

data declaration (ada)

Started : boolean := false;

data access from pseudo_code

(da) room.Started IS USED BY NONE

data access from Ada code

(da) room.Started IS USED BY 
        (op) room.start_serving [R]

data access from C code

(da) room.Started IS USED BY NONE

data access from C++ code

(da) room.Started IS USED BY NONE

OBJECT_CONTROL_STRUCTURE

obcs body description (text)

OBCS is automatically generated from STD and operation constraints.

state transition diagram

waiting

exiting transitions

starting

state description (text)

Initial state. Started is set to FALSE.

state assignment (ada)

Started := false;

state test (ada)

not Started

dining

entering transitions

starting, serving

exiting transitions

serving

state description (text)

Running state. Started is set to TRUE.

state assignment (ada)

Started := true;

state test (ada)

Started

starting

transition event

start_serving

transition from

waiting

transition to

dining

trans description (text)

This transition is triggered by Start_Serving execution request.
No additional condition, neither exception code is required.

serving

transition event

report_state

transition from

dining

transition to

dining

trans description (text)

This transition is triggered by Report_Sta        te execution request.
No additional condition, neither exception code is required.
Current state is not changed.

OPERATION_CONTROL_STRUCTURES

OPERATION start_serving IS

operation body description (text)

Performs following actions:
- Calculates Start_Time;
- Puts chopsticks on the table;
- Assigns Philosophers to seats at the table;
- Opens and draw a window to observe each seat;
- Assigns right and left chopsticks to each Philosopher;

used operations

calendar.Clock
windows.open
windows.borders
phil.start_eating

operation code (ada)

begin

  -- starting date is stored:
  Start_Time := Calendar.Clock;

  -- chopsticks are put on the table:
  Sticks :=
    (S1'Access,
     S2'Access,
     S3'Access,
     S4'Access,
     S5'Access);

  -- philosophers are assigned to seats at the table
  Phils :=
    (P1'Access,
     P3'Access,
     P5'Access,
     P4'Access,
     P2'Access);

  -- which seat each phil occupies:
  Phil_Seats := (1, 3, 5, 4, 2); 

  -- a window is open for each seat:
  Phil_Windows :=
    (Windows.Open(( 1, 24), 7, 30),
     Windows.Open(( 9,  2), 7, 30),
     Windows.Open(( 9, 46), 7, 30),
     Windows.Open((17,  7), 7, 30),
     Windows.Open((17, 41), 7, 30));

  -- windows borders are drawn:
  for Which_Win in Phil_Windows'range loop
    Windows.Borders(Phil_Windows(Which_Win),'+','|','-');
  end loop;

  -- philosophers are assigned their chopsticks:
  Phils (1).Start_Eating(1, 1, 2);
  Phils (3).Start_Eating(3, 3, 4);
  Phils (2).Start_Eating(2, 2, 3);
  Phils (5).Start_Eating(5, 1, 5);
  Phils (4).Start_Eating(4, 4, 5);

  -- dining room state changes:
  Started := true;

call tree from Ada code

END start_serving

OPERATION report_state IS

operation body description (text)

Performs following actions:
- Calculates current time;
- Displays a message on relevant window.

used operations

calendar.Clock
windows.title
society.get_name
windows.put
windows.new_line

operation code (ada)

begin

  T := Natural (Calendar.Clock - Start_Time);

  case Which_State is

    when Phil.Breathing =>
      Windows.Title(
          Phil_Windows(Phil_Seats(Which_Phil)),
          Society.Get_Name(Which_Phil), '-');
      Windows.Put(
          Phil_Windows(Phil_Seats(Which_Phil)),
          "T =" & Integer'Image (T) & " " & "Breathing...");
      Windows.New_Line(Phil_Windows(Phil_Seats(Which_Phil)));

    when Phil.Thinking =>
      Windows.Put(
          Phil_Windows(Phil_Seats(Which_Phil)),
          "T =" & Integer'Image (T) & " " & "Thinking"
          & Integer'Image (How_Long) & " seconds.");
      Windows.New_Line(Phil_Windows(Phil_Seats(Which_Phil)));

    when Phil.Eating =>
      Windows.Put(
          Phil_Windows(Phil_Seats(Which_Phil)),
          "T =" & Integer'Image (T) & " " & "Meal"
          & Integer'Image (Which_Meal) & ","
          & Integer'Image (How_Long) & " seconds.");
      Windows.New_Line(Phil_Windows(Phil_Seats(Which_Phil)));

    when Phil.Done_Eating =>
      Windows.Put(
          Phil_Windows(Phil_Seats(Which_Phil)),
          "T =" & Integer'Image (T) & " " & "Yum-yum (burp)");
      Windows.New_Line(Phil_Windows(Phil_Seats(Which_Phil)));

    when Phil.Got_One_Stick =>
      Windows.Put(
          Phil_Windows(Phil_Seats(Which_Phil)),
          "T =" & Integer'Image (T) & " " & "First chopstick"
          & Integer'Image (How_Long));
      Windows.New_Line(Phil_Windows(Phil_Seats(Which_Phil)));

    when Phil.Got_Other_Stick =>
      Windows.Put(
          Phil_Windows(Phil_Seats(Which_Phil)),
          "T =" & Integer'Image (T) & " " & "Second chopstick"
          & Integer'Image (How_Long));
      Windows.New_Line(Phil_Windows(Phil_Seats(Which_Phil)));

    when Phil.Dying =>
      Windows.Put(
          Phil_Windows(Phil_Seats(Which_Phil)),
          "T =" & Integer'Image (T) & " " & "Croak");
      Windows.New_Line(Phil_Windows(Phil_Seats(Which_Phil)));

  end case; -- Which_State

call tree from Ada code

END report_state

OPERATION get_stick IS

operation body description (text)

Just returns a pointer to specified chopstick.

operation code (ada)

begin
  return Sticks(Which_Stick);

call tree from Ada code

END get_stick

END room