7.5. Example of a Table Management Package


The following example illustrates the use of packages in providing high level procedures with a simple interface to the user.

The problem is to define a table management package for inserting and retrieving items. The items are inserted into the table as they are supplied. Each inserted item has an order number. The items are retrieved according to their order number, where the item with the lowest order number is retrieved first.

From the user's point of view, the package is quite simple. There is a type called ITEM designating table items, a procedure INSERT for inserting items, and a procedure RETRIEVE for obtaining the item with the lowest order number. There is a special item NULL_ITEM that is returned when the table is empty, and an exception TABLE_FULL which is raised by INSERT if the table is already full.

A sketch of such a package is given below. Only the specification of the package is exposed to the user.

    package TABLE_MANAGER is 

       type ITEM is
             ORDER_NUM : INTEGER;
             ITEM_CODE : INTEGER;
             QUANTITY  : INTEGER;
             ITEM_TYPE : CHARACTER;
          end record; 

       NULL_ITEM : constant ITEM :=
          (ORDER_NUM | ITEM_CODE | QUANTITY => 0, ITEM_TYPE => ' ');   

       procedure INSERT  (NEW_ITEM   : in  ITEM);
       procedure RETRIEVE(FIRST_ITEM : out ITEM); 

       TABLE_FULL : exception;  --  raised by INSERT when table full

The details of implementing such packages can be quite complex; in this case they involve a two-way linked table of internal items. A local housekeeping procedure EXCHANGE is used to move an internal item between the busy and the free lists. The initial table linkages are established by the initialization part. The package body need not be shown to the users of the package.

    package body TABLE_MANAGER is
       SIZE : constant := 2000;
       subtype INDEX is INTEGER range 0 .. SIZE; 

       type INTERNAL_ITEM is
             CONTENT : ITEM;
             SUCC    : INDEX;
             PRED    : INDEX;
          end record; 

       TABLE : array (INDEX) of INTERNAL_ITEM;
       FIRST_BUSY_ITEM : INDEX := 0;
       FIRST_FREE_ITEM : INDEX := 1; 

       function FREE_LIST_EMPTY return BOOLEAN is ... end;
       function BUSY_LIST_EMPTY return BOOLEAN is ... end;
       procedure EXCHANGE (FROM : in INDEX; TO : in INDEX) is ... end; 

       procedure INSERT (NEW_ITEM : in ITEM) is
          if FREE_LIST_EMPTY then
             raise TABLE_FULL;
          end if;
          --  remaining code for INSERT
       end INSERT; 

       procedure RETRIEVE (FIRST_ITEM : out ITEM) is ... end; 

       --  initialization of the table linkages
    end TABLE_MANAGER;