[net.lang.ada] Need to see certain data inside a task type.

LARMSTRONG%rca.com@RELAY.CS.NET ("LEN ARMSTRONG ", SYSTEMS LAB) (10/13/86)

OK, I need some help -- anyone wanna' volunteer?

I have a construct similar to the following:

package P is
   task type T is
      entry E1; -- Entries are really unimportant for this example.
      entry E2;
   end T;
   type TR (PARAM_FIELD : <SOME_TYPE>) is
      record
         TASK_FIELD : T;
      end record;
   XX : TR(<SOME_CONSTANT_VALUE_OF_<SOME_TYPE>>)
end P;

However, my problem comes in when I am in the body of the task type T.  I
need to access inside XX.TASK_FIELD the value held by XX.PARAM_FIELD.  Does
anyone know of anyway I can do this?  For some reason, I feel my chances of
being allowed to do it are very slim.

I would really like to be able to keep the lexical structure I am currently
using (as defined above) but other solutions are welcome also.

Thanks,
Len

LArmstrong%Henry@RCA.Com

gary@telesoft.UUCP@ndmce.uucp (Gary Dismukes @lizard) (10/18/86)

In response to Len Armstrong's question regarding tasks and discriminants:


Since the access that a task has to data outside of its body is essentially
limited to visible objects declared prior to the task body and to data passed
in as entry parameters, there is no way for a task to directly access a
discriminant of a record type containing the task as a component.  At one
point during the language design process there was some discussion of allowing
discriminants to be declared for task types.  However, this was not long before
the standardization of Ada and it was felt that not enough time was available
to give the necessary attention to integrating such a feature so it was not
added.  There is, however, a way to achieve the basic functionality that you
are looking for.  One approach to solving the problem would be to require an
explicit call to an initialization entry after the declaration of the record
object.  Using the given example we would have:

  declare
    X: TR( SOME_VALUE_OF_SOME_TYPE );
  begin
    X.TASK_FIELD.INITIALIZE( X.PARAM_FIELD );
    ...
  end;

This is clearly undesirable because of the separation of the declaration
and initialization of the object.  We would prefer that the user of the
type TR need not be concerned with the initialization of the task.

An alternative approach is to introduce an access type and initialization
function as shown below:


  package PKG is
  
    task type T is
       entry INITIALIZE ( INIT_PARAM: SOME_TYPE );
       entry E1;
       entry E2;
    end T;
   
    type T_ACCESS is access T;
   
    function T_INIT ( INIT_PARAM: SOME_TYPE ) return T_ACCESS;
   
    type TR ( PARAM_FIELD: SOME_TYPE ) is
      record
        TASK_FIELD : T_ACCESS := T_INIT( PARAM_FIELD );
      end record;
   
  end PKG;

  package body PKG is
   
    task body T is
      PARAMETER: SOME_TYPE;
    begin
      accept INITIALIZE ( INIT_PARAM: SOME_TYPE ) do
        PARAMETER:= INIT_PARAM;
      end INITIALIZE;
        ...
    end T;

    function T_INIT ( INIT_PARAM: SOME_TYPE ) return T_ACCESS is
      NEW_T: T_ACCESS := new T;
    begin
      NEW_T.INITIALIZE( INIT_PARAM );
      return NEW_T;
    end T_INIT;

  end PKG;


It then suffices to declare an object of type PKG.TR with the appropriate
discriminant constraint:
  
    XX : PKG.TR( SOME_VALUE_OF_SOME_TYPE );

This solution encapsulates the creation and initialization of the task object
within a function and relies on the ability to use a discriminant in the
default value expression for a record component.  The replacement of the
task component with an access component is largely transparent to the user
because of the implicit dereferencing for entry calls (e.g., XX.TASK_FIELD.E1).
The main disadvantage is that, if deallocation of the task object is an
important concern, an explicit unchecked deallocation will be necessary
unless the implementation supports garbage collection.

There is also a fundamental limitation in using discriminants to parameterize
tasks because the type of a discriminant is restricted by the language to being
a discrete type, but this may not matter for the application considered.


  Gary Dismukes
  TeleSoft

Bryan@SIERRA.STANFORD.EDU@ndmce.uucp (Doug Bryan) (10/18/86)

Here is an idea for you... let me know if you get anything better.

doug
........................

generic
package Pack is
    task type T is
	entry My_Discriminant   (D : Integer);
	entry Echo_Discriminant;
    end T;
    type Acc is access T;
    function F (D : Integer) return Acc;
    type Rec (D : Integer) is
	record
	    Acc_T : Acc := F (D);
	end record;
end Pack;
-------------------------------

with Text_Io;
package body Pack is
    function F (D : Integer) return Acc is
	A : Acc := new T;
    begin
	A.My_Discriminant (D);
	return A;
    end F;

    task body T is
	Local_Discriminant : Integer;
    begin
	accept My_Discriminant (D : Integer) do
	    Local_Discriminant := D;
	end My_Discriminant;
	accept Echo_Discriminant;
	Text_Io.Put_Line (Integer'Image (Local_Discriminant));
    end T;
end Pack;
-------------------------------

with Pack;
procedure Disc_Task is
    package P is new Pack;

-- Pack is generic in order to force elaboration of body before
-- the following objects are elaborated.

    Rec_1 : P.Rec (1);
    Rec_2 : P.Rec (2);
    Rec_3 : P.Rec (3);
begin
    Rec_1.Acc_T.Echo_Discriminant;
    Rec_2.Acc_T.Echo_Discriminant;
    Rec_3.Acc_T.Echo_Discriminant;
end Disc_Task;

-------