comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Class with task destructor
Date: Tue, 22 Nov 2011 18:44:39 -0800 (PST)
Date: 2011-11-22T18:44:39-08:00	[thread overview]
Message-ID: <80027d05-2740-4899-b43a-514100ec9bd2@p16g2000yqd.googlegroups.com> (raw)
In-Reply-To: 30604696.94.1322013045135.JavaMail.geo-discussion-forums@yqzz20

Although I haven't looked into this too rigorously, I think the
problem (with the first implementation) is that neither "terminate"
alternative in the task is given a chance to work.  First of all, you
have "select accept Start; ... or terminate;" (the second "or
terminate, toward the end of Primary_Task).  Start is called right
away, so we go into that branch.  Then we go into Main_Loop, and you
have a select with three alternatives: accept Pause; accept Finish; or
an "else" that will get executed right away if nobody is calling Pause
and Finish.  Pause isn't called anywhere, and in your first
implementation Finish isn't called everywhere.  Thus, the select goes
right to the "else" branch, which does a Put and a delay, then you
loop back to do it again, and since Pause and Finish aren't still
being called, it goes to the Put and delay again, and it keeps going
round and round and round.  The inner "select" that has the terminate
alternative never gets executed since you have to accept Pause first,
and the outer "select" with the terminate alternative never gets
executed since you never get out of Main_Loop.  So the "terminate"
alternatives in your task never have any effect.

The language rules say that Unchecked_Deallocation doesn't force tasks
to terminate.  I believe he only way to terminate a task that doesn't
terminate on its own (either by leaving the task body, or by a
terminate alternative) is to use ABORT (or
Ada.Task_Identification.Abort_Task).  And I wouldn't do that if there
are other ways to get a task to terminate.

                        -- Adam




On Nov 22, 5:50 pm, "Rego, P." <pvr...@gmail.com> wrote:
> So now I have a class with a task inside and a Constructor, and I want to implement a destructor.
>
> --test_pkg.ads
> with Unchecked_Deallocation;
> package Test_Pkg is
>
>    type Test_Class is tagged;
>    type Test_Class_Ptr is access all Test_Class;
>
>    function Construct return Test_Class_Ptr;
>    procedure Destruct (T : access Test_Class);
>
>    task type Primary_Task (This : not null access Test_Class) is
>       entry Start;
>       entry Pause;
>       entry Release;
>       entry Finish;
>    end Primary_Task;
>
>    type Test_Class is tagged limited
>       record
>          Some_Info : Integer;
>          Primary   : Primary_Task (Test_Class'Access);
>       end record;
>
>    procedure Free is new Unchecked_Deallocation (Object => Test_Class,
>                                                  Name   => Test_Class_Ptr);
> end Test_Pkg;
>
> --test_pkg_main.adb
> with Test_Pkg; use Test_Pkg;
>
> procedure Test_Pkg_Main is
>    Obj_Ptr : Test_Class_Ptr;
> begin
>    Obj_Ptr := Construct;
>    delay 5.0;
>    Obj_Ptr.Destruct;
>
> end Test_Pkg_Main;
>
> --test_pkg.adb
> with Text_IO; use Text_IO;
> package body Test_Pkg_Rev661 is
>    task body Primary_Task is
>    begin
>       Outer_Loop : loop
>          select
>             accept Start;
>             Main_Loop : loop
>                select
>                   accept Pause;
>                   select
>                      accept Release;
>                   or
>                      accept Finish;
>                      exit Outer_Loop;
>                   or
>                      terminate;
>                   end select;
>                or
>                   accept Finish;
>                   exit Outer_Loop;
>                else
>                   Put ("^"&Integer'Image (This.Some_Info));
>                   delay 0.5;
>                end select;
>             end loop Main_Loop;
>          or
>             terminate;
>          end select;
>       end loop Outer_Loop;
>    end Primary_Task;
>
>    function Construct return Test_Class_Ptr is
>       T_Ptr : constant Test_Class_Ptr := new Test_Class;
>    begin
>       T_Ptr.Some_Info := 1;
>       T_Ptr.Primary.Start;
>       return T_Ptr;
>    end Construct;
>
>    procedure Destruct (T : access Test_Class) is
>    ...
>    end Destruct;
> end Test_Pkg_Rev661;
>
> --
> (1) So, the first implementation I tried was
>    procedure Destruct (T : access Test_Class) is
>       T_Ptr : Test_Class_Ptr := Test_Class_Ptr (T);
>    begin
>       Free (T_Ptr);
>    end Destruct;
>
> So I thought that if I unallocate the object, the task inside would be dead too, because the object would be its master. It looks that I'm wrong, because the execution led me to
>
> ^ 1^ 1^ 1^ 1^ 1^ 1^ 1^ 1^ 1^ 1^ 6295912^ 6295912^ (...)
> then the task is not dead after the object dies.
> So why is this implementation wrong?
>
> (2) The second one implementation I tried, which looks me that led me to a (happy) program termination was
>    procedure Destruct (T : access Test_Class) is
>       T_Ptr : Test_Class_Ptr := Test_Class_Ptr (T);
>    begin
>       T.Primary.Finish;
>       Free (T_Ptr);
>    end Destruct;
>
> and the execution leds me to
> ^ 1^ 1^ 1^ 1^ 1^ 1^ 1^ 1^ 1^ 1 (and no more)
>
> I agree that in this case the task is dead, because of the forced termination. And so on the object itself. But is this implementation preferable over the first one?
>
> Thank you again.




  reply	other threads:[~2011-11-23  2:44 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-23  1:50 Class with task destructor Rego, P.
2011-11-23  2:44 ` Adam Beneschan [this message]
2011-11-23  5:04   ` Yannick Duchêne (Hibou57)
2011-11-23  6:14     ` Adam Beneschan
2011-11-24  0:15       ` Randy Brukardt
2011-11-24  2:48         ` Adam Beneschan
2011-11-29  3:36           ` Randy Brukardt
2011-11-29  9:31             ` Simon Wright
2011-11-29 15:37             ` Adam Beneschan
2011-11-23  8:35 ` Dmitry A. Kazakov
2011-11-23  9:05   ` Simon Wright
2011-11-23 10:41     ` Dmitry A. Kazakov
2011-11-30  1:11     ` Rego, P.
2011-11-30  2:21       ` Adam Beneschan
2011-11-30  8:41         ` Dmitry A. Kazakov
2011-12-01  0:35           ` Randy Brukardt
2011-12-01  6:28             ` J-P. Rosen
2011-12-01 10:55               ` Simon Wright
2011-12-01 21:48               ` Robert A Duff
2011-12-01 22:44                 ` Adam Beneschan
2011-12-02  0:57                 ` Randy Brukardt
2011-12-02  5:57                 ` J-P. Rosen
2011-12-02 15:07                   ` Robert A Duff
2011-12-02 18:41                   ` Jeffrey Carter
2011-12-01  9:25             ` Dmitry A. Kazakov
2011-12-01  1:58         ` Rego, P.
2011-11-30  8:35       ` Simon Wright
2011-11-30 15:36         ` Adam Beneschan
2011-11-30 16:32           ` Robert A Duff
2011-12-01  0:40             ` Randy Brukardt
2011-12-01  8:50               ` Yannick Duchêne (Hibou57)
2011-12-02  0:50                 ` Randy Brukardt
2011-12-02  5:30                   ` Jeffrey Carter
2011-12-02 16:20                     ` Adam Beneschan
2011-12-02 18:01                       ` Dmitry A. Kazakov
2011-12-02 18:50                       ` Jeffrey Carter
2011-12-02 19:03                         ` Adam Beneschan
2011-12-01 10:51           ` Simon Wright
2011-12-01 22:59             ` Simon Wright
2011-12-01  1:59         ` Rego, P.
2011-11-30  1:47     ` Rego, P.
     [not found]     ` <15090042.1880.1322617401962.JavaMail.geo-discussion-forums@yqkn8>
2011-11-30  8:43       ` Dmitry A. Kazakov
2011-12-01  1:53         ` Rego, P.
2011-12-01  9:28           ` Dmitry A. Kazakov
2011-11-25  2:44   ` Rego, P.
     [not found]   ` <28489797.1088.1322188495508.JavaMail.geo-discussion-forums@yqf20>
2011-11-25  9:19     ` Dmitry A. Kazakov
2011-11-29  3:40       ` Randy Brukardt
2011-11-23 10:26 ` Brian Drummond
2011-11-25  1:37   ` Rego, P.
2011-11-25 13:40     ` Brian Drummond
replies disabled

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