comp.lang.ada
 help / color / mirror / Atom feed
* Concurrency and interfaces
@ 2008-01-28 15:34 Philippe Tarroux
  2008-01-29 13:37 ` Stephen Leake
  0 siblings, 1 reply; 2+ messages in thread
From: Philippe Tarroux @ 2008-01-28 15:34 UTC (permalink / raw)


Hi everybody,

I try to explore the Ada05 interfaces in the context of concurrency. My 
original question was to explore different solutions for the following 
problem:

How to connect a task (T2) to other tasks (T11 or T12) having different 
functionalities depending on a given context.

I abstracted the following code :

package Test_Interfaces is

   type Int1 is synchronized interface;
   procedure Init (I1 : in out Int1) is abstract;
 
   type Int1_Ptr is access Int1'Class;

   type Int2 is synchronized interface;
   procedure Process(I1 : in out Int2) is abstract;

   task type T11 is new Int1 with
      entry Init;
   end T11;

   task type T12 is new Int1 and Int2 with
      entry Init;
      entry Process;  -- Some additional functionalities
   end T12;
 
   task type T2 is
      entry Connect (T : Int1'Class);
   end T2;
     
end Test_Interfaces;

with Text_Io;
use Text_Io;

package body Test_Interfaces is

   task body T11 is
   begin
      accept Init do
     Put ("Init T11"); New_Line;
      end Init;
      loop
     delay 0.5;
     Put ("Process T11"); New_Line;
      end loop;
   end T11;

   task body T12 is
   begin
      accept Init do
     Put ("Init T12"); New_Line;
      end Init;
      loop
         select
         delay 0.1;
            Put ("Process T12"); New_Line;
         or
            accept Process; -- some extra processing
          end select;
        end loop;
   end T12;
 
   task body T2 is
      Int_Task : Int1_Ptr;
   begin
      accept Connect (T : Int1'Class) do
     Put("External task connection"); New_Line;
     Int_Task := new Int1'Class'(T);
      end Connect;
      Int_Task.Init;
   end T2;

end Test_Interfaces;

Then the main program:

with Test_Interfaces;
use Test_Interfaces;

procedure test_tasking is 
   Task11 : T11;
   Task12 : T12;
  
   Task2 : T2;
begin
   Task2.Connect (Task12);
end test_tasking;

In this case, the program is blocked in the Connect call.

When Task11 is used instead Task12, I get a PROGRAM ERROR : unhanded 
signal. I dont understand why these two situations are not symmetrical 
and give rise to different behaviors.

When I replace the declaration of Int_Task in task body T2 by Int_Task : 
access Int1'class; the builder raises the following error:

undefined reference to 'test_interface__t2___master'

When I replace Int1'class by Int1_Ptr :

...
   task type T2 is
      entry Connect (T : Int1_Ptr);
   end T2;
...

   task body T2 is
      Int_Task : Int1_Ptr;
   begin
      accept Connect (T : Int1_Ptr) do
     Put("External task connection"); New_Line;
     Int_Task := T;
      end Connect;
      Int_Task.Init;
   end T2;

...
with Test_Interfaces;
use Test_Interfaces;

procedure test_tasking is 
   Task11 : Int1_Ptr := new T11;
   Task12 : Int1_Ptr := new T12;
  
   Task2 : T2;
begin
   Task2.Connect (Task11);  -- or Task2.Connect(Task12);
end test_tasking;

all runs correctly.

I suspect the conjunction of a faulty construct  at the level of the 
affectation Int_Task := new Int1'Class'(T); incorrectly handled by the 
compiler but i don't really understand why this construct is illegal.

I conclude that there is no way to hide the use of the pointer Int1_Ptr 
and probably no way to do that statically.

Any idea?

Philippe Tarroux
philippe.tarroux@limsi.fr

OS : WXP
Ada compiler : gcc 4.1.3 20070403 for GNAT GPL 2007 (20070402)









^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Concurrency and interfaces
  2008-01-28 15:34 Concurrency and interfaces Philippe Tarroux
@ 2008-01-29 13:37 ` Stephen Leake
  0 siblings, 0 replies; 2+ messages in thread
From: Stephen Leake @ 2008-01-29 13:37 UTC (permalink / raw)


Philippe Tarroux <philippe.tarroux@limsi.fr> writes:

> package Test_Interfaces is
>
>    type Int1 is synchronized interface;
> <snip>
>
> package body Test_Interfaces is
>
> <snip>
>   task body T2 is
>       Int_Task : Int1_Ptr;
>    begin
>       accept Connect (T : Int1'Class) do
>      Put("External task connection"); New_Line;
>      Int_Task := new Int1'Class'(T);

This is illegal; you are allocating an object of type Int1, and
initializing it. But synchronized types are limited (ARM 3.9.4 (5)),
so you can't do that.

The compiler doesn't recognize that the code is illegal; that's a
compiler bug.

With GNAT 6.1.0w, I get:

test_interfaces.adb:39:22: initialization not allowed for limited types

> When Task11 is used instead Task12, I get a PROGRAM ERROR : unhanded
> signal. I dont understand why these two situations are not symmetrical
> and give rise to different behaviors.

Since the compiler has a bug, it's not surprising it generates buggy
code :).

> When I replace Int1'class by Int1_Ptr :
>
> ...
>    task type T2 is
>       entry Connect (T : Int1_Ptr);
>    end T2;
> ...
>
>    task body T2 is
>       Int_Task : Int1_Ptr;
>    begin
>       accept Connect (T : Int1_Ptr) do
>      Put("External task connection"); New_Line;
>      Int_Task := T;

Now this is legal; you are copying a pointer.

>       end Connect;
>       Int_Task.Init;
>    end T2;
>
> all runs correctly.
>
> I suspect the conjunction of a faulty construct  at the level of the
> affectation Int_Task := new Int1'Class'(T); incorrectly handled by the
> compiler but i don't really understand why this construct is
> illegal.

The short answer is "Int1 is limited". The reason it's limited is that
it might be a task, and tasks are limited, because what would it mean
to copy a task?

In the statement

      Int_Task := new Int1'Class'(T);

are you trying to create a new task, or just get a reference to an
existing one?

If you want a reference, then passing in the pointer is necessary.

If you are trying to create a new one, then you need some sort of
factory, and you _don't_ want to create a task in the test_tasking
main program.

Your initial problem statement sounded more like you wanted a
reference, not to create a new task.

> I conclude that there is no way to hide the use of the pointer
> Int1_Ptr and probably no way to do that statically.

Right. But that's good; the semantics of your program requires a
reference, so you should declare a reference.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-01-29 13:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-01-28 15:34 Concurrency and interfaces Philippe Tarroux
2008-01-29 13:37 ` Stephen Leake

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