comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Tasks, Entries, and Variables of a Class-wide type
Date: Mon, 1 Nov 2010 10:21:09 +0100
Date: 2010-11-01T10:21:09+01:00	[thread overview]
Message-ID: <ckmpf7cxf86x$.123uob2jwdt0z$.dlg@40tude.net> (raw)
In-Reply-To: 7e77bb8f-17b6-4d51-9946-ea825f726682@f33g2000yqh.googlegroups.com

On Sun, 31 Oct 2010 22:40:37 -0700 (PDT), Shark8 wrote:

> IοΏ½d originally wanted to have something like this:
> 
> Task Type Parser_Task is
>  Entry Parse( Input : in out String ) Return PostScript_ObjectοΏ½Class;
> End Parser;

This does not make sense, because it would parse during a rendezvous. So
the effect on the caller would be same as if the caller would parse on its
own context. Why not to make parsing a plain function then?

In order to take an advantage of tasking it should be like:

task type Parser_Task is
   entry Request_Parsing (Input : String);
   entry Wait_For_Result (Output : out Post_Script_Object);
end Parser;

> is invalid because the tags wonοΏ½t match. We now have the problem where
> the class-wide type needs to know what particular object the parser
> will return, and the parser needs that class-wide variable wherein to
> store the type in the first place. {A programming Catch-22 or Chicken/
> Egg problem}
> 
> I figured out how to work around this problem, however. Inside the
> Parser_Task we can do something like the following:
> 
> Task body Parse_Task is
> [...]
> Accept Parse( Input : in out String; Object : Out
> PostScript_ObjectοΏ½Class ) do
>    Declare
>       Temp : PostScript_ObjectοΏ½Class:= Parse_Function( Input );
>      For TempοΏ½Address use OutputοΏ½Address;
>    Begin
>       Null;
>    End;
> End Parse;
> [...]

A bad idea.

What you could do is to use the generic dispatching constructor (ARM 3.9).
Here is the outline:

   package Parsers is
      type Parser_Task;
      type Post_Script_Object is tagged null record;
      function Constructor (Parser : not null access Parser_Task)
         return Post_Script_Object;
      task type Parser_Task is
         entry Request (Input : String);
         entry Wait_For_Result (Output : out Tag);
         entry Get_Result (Output : out Post_Script_Object'Class);
      end Parser_Task;
      function Get_Object is
         new Ada.Tags.Generic_Dispatching_Constructor
             (Post_Script_Object, Parser_Task, Constructor);
   end Parsers;

The implementation:

   package body Parsers is
      function Constructor (Parser : not null access Parser_Task)
         return Post_Script_Object is
      begin
         return Result : Post_Script_Object do
            Parser.Get_Result (Result);
         end return;
      end Constructor;

      task body Parser_Task is
         Source : Unbounded_String;
      begin
         loop
            select
               accept Request (Input : String) do
                  Source := To_Unbounded_String (Input);
               end Request;
            or terminate;
            end select;
            -- Here we parsing the stuff in Source. It will create all
            -- sorts of objects derived from Post_Script_Object.
            -- For example:
            declare
               Result : Post_Script_Object'Class :=
                  Post_Script_Object'(null record);
            begin
               accept Wait_For_Result (Output : out Tag) do
                  Output := Result'Tag;
               end Wait_For_Result;
               accept Get_Result (Output : out Post_Script_Object'Class) do
                  Output := Result;
               end Get_Result;
            end;
         end loop;
      end Parser_Task;
   end Parsers;

Note, you will need to override Constructor for each type derived from
Post_Script_Object.

Here is how to use it on the client side:

   Worker : aliased Parser_Task;
begin
   Worker.Request ("...");
   declare
      Result_Type : Tag;
   begin
      Worker.Wait_For_Result (Result); -- Now we know the type
      declare
         Object : Post_Script_Object'Class :=
            Get_Object Result_Type, Worker'Access);
      begin
         -- Doing something with object;
      end;
   end;

Note, you can also pack Wait_For_Result into Constructor, but then you will
not be able to wait for the parser in a timed entry call.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



  reply	other threads:[~2010-11-01  9:21 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-01  5:40 Tasks, Entries, and Variables of a Class-wide type Shark8
2010-11-01  9:21 ` Dmitry A. Kazakov [this message]
2010-11-01 15:30   ` Shark8
2010-11-01 18:50     ` Jeffrey Carter
2010-11-01 19:23       ` Dmitry A. Kazakov
2010-11-01 20:08         ` Georg Bauhaus
2010-11-01 20:56           ` Dmitry A. Kazakov
2010-11-01 19:28       ` Shark8
2010-11-01 20:49         ` Jeffrey Carter
2010-11-05 12:43         ` Robert A Duff
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox