comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Task with access to itself?
Date: Thu, 6 Dec 2012 11:53:32 -0800 (PST)
Date: 2012-12-06T11:53:32-08:00	[thread overview]
Message-ID: <caa635ca-5a30-4c93-a802-00f1d7954263@googlegroups.com> (raw)
In-Reply-To: <93da19a9-acaf-4395-98d0-33baf5a04bd0@googlegroups.com>

On Thursday, December 6, 2012 1:38:41 AM UTC-8, Egil Høvik wrote:
> On Wednesday, December 5, 2012 2:53:53 PM UTC+1, Jacob Sparre Andersen wrote:

> Having the tasks grabbing jobs from a protected objects is probably a better idea, but this seems to work on GNAT Pro 7.0.2:
> 
> package foo is
> 
>    task type Handler is
>       entry Do_Stuff;
>    end Handler;
> 
>    type Reference is access all Handler;  
> 
>    procedure Register_As_Available(P : access Handler);
>    function Get_Next return Reference;
> 
> end foo;
> 
> 
> with Ada.Task_Identification;
> with Ada.Text_IO;
> 
> package body foo is
> 
>    task body Handler is
>    begin
>       Register_As_Available(Handler'Access); -- Handler here refers to the current instance of the type
>       loop
>          select 
>             accept Do_Stuff do
>                Ada.Text_IO.Put_Line("foo" & Ada.Task_Identification.Image(Handler'Identity));
>             end Do_Stuff;
>          or 
>             terminate;
>          end select;
>       end loop;
>    end Handler;
> 
>    List : array(1..2) of Reference;
>    Last : Natural := 0;
>    
>    procedure Register_As_Available(P : access Handler)
>    is
>    begin
>       Last := Last + 1;
>       List(Last) := Reference(P);
>    end Register_As_Available;
> 
>    Next : Natural := 0;
>    function Get_Next return Reference is
>    begin
>       Next := Next + 1;
>       if Next > List'Last then
>          Next := 1;
>       end if;
>       return List(Next);
>    end Get_Next;
> end foo;
> 
> 
> with foo;
> 
> procedure bar is
> 
>    t1 : foo.handler;
>    t2 : foo.handler;
> 
>    Ref : foo.Reference;
> begin
> 
>    for i in 1..10 loop
>       Ref := foo.Get_Next;
>       Ref.Do_Stuff;
>    end loop;
> 
> end bar;
> 
> 
> (If you're not careful, you may end up with a bunch of accessibility issues, though)

This program *does* have accessibility issues.  It works only because GNAT is known to have problems catching accessibility-level violations.  The accessibility of Handler is deeper than that of the Reference type; therefore, when this is executed:

  Register_As_Available(Handler'Access)

a Constraint_Error should be raised when Register_As_Available converts its parameter to Reference.  To see this, suppose you have a nested procedure that declares its own Nested_Task : foo.Handler.  Nested_Task would put an access to itself in the List array.  Then the nested procedure exits and Nested_Task is no more, but an access to it still lives in the List.  In Ada, if you don't use 'Unchecked_Access or other constructs that let you get around the rules, you can't have an access object that outlives the thing it's pointing to (except when there's a hole in the language; but there isn't, at least in this case).  So that should be enough to convince anyone that this program shouldn't work.

Changing the above to

  Register_As_Available(Handler'Unchecked_Access)

should make things work, although then the programmer has to be careful to write things in a way so that dangling references aren't used.  Also, the above program has some other problems: (1) both tasks could execute Register_As_Available at the same time, which could really screw things up if the both increment Last before either of them stores into the array; and (2) the main subprogram's code could execute before either task has a chance to call Register_As_Available, meaning that Ref could be null and the program could bomb that way.  If your program "seems" to work, it's because you got lucky (in addition to the compiler problem that is causing an accessibility check to be missed).

                         -- Adam




      reply	other threads:[~2012-12-06 19:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-05 13:53 Task with access to itself? Jacob Sparre Andersen
2012-12-05 14:18 ` Dmitry A. Kazakov
2012-12-05 16:57 ` Jeffrey Carter
2012-12-11 11:21   ` Jacob Sparre Andersen
2012-12-11 20:39     ` Jeffrey Carter
2012-12-12 20:25       ` Jacob Sparre Andersen
2012-12-12 21:11         ` Jeffrey Carter
2012-12-13  7:20           ` Jacob Sparre Andersen
2012-12-06  9:38 ` Egil Høvik
2012-12-06 19:53   ` Adam Beneschan [this message]
replies disabled

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