comp.lang.ada
 help / color / mirror / Atom feed
* Delayed deallocation of non-terminated task in Gnat?
@ 2011-08-30 13:22 Marc C
  2011-08-30 15:20 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Marc C @ 2011-08-30 13:22 UTC (permalink / raw)


Saw this pop up in AdaCore's Developer Center notices:

>[GNAT] Automatic deallocation of task upon termination
>
>Monday August 29, 2011
>
>If Unchecked_Deallocation is called on a non-terminated task (which was previously a no-op),
>the task is now marked to be freed automatically when it terminates.

[http://www.adacore.com/2011/08/29/NF-65-H911-007-gnat/]

This *looks* to me like one could dynamically allocate a task instance
and then immediately free it with an instantiation of
Unchecked_Deallocation, yet the task would continue to function
normally until it terminates.

This seems rather a stretch to me, is there more to this than this
brief summary lets on?

Marc A. Criley



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 13:22 Delayed deallocation of non-terminated task in Gnat? Marc C
@ 2011-08-30 15:20 ` Dmitry A. Kazakov
  2011-08-31 18:12   ` Robert A Duff
  2011-08-30 15:38 ` Adam Beneschan
  2011-08-31 18:08 ` Robert A Duff
  2 siblings, 1 reply; 21+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-30 15:20 UTC (permalink / raw)


On Tue, 30 Aug 2011 06:22:43 -0700 (PDT), Marc C wrote:

> Saw this pop up in AdaCore's Developer Center notices:
> 
>>[GNAT] Automatic deallocation of task upon termination
>>
>>Monday August 29, 2011
>>
>>If Unchecked_Deallocation is called on a non-terminated task (which was previously a no-op),
>>the task is now marked to be freed automatically when it terminates.
> 
> [http://www.adacore.com/2011/08/29/NF-65-H911-007-gnat/]
> 
> This *looks* to me like one could dynamically allocate a task instance
> and then immediately free it with an instantiation of
> Unchecked_Deallocation, yet the task would continue to function
> normally until it terminates.

Does it mean that Unchecked_Deallocation won't wait for the task to
terminate? That would be surprising.

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



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 13:22 Delayed deallocation of non-terminated task in Gnat? Marc C
  2011-08-30 15:20 ` Dmitry A. Kazakov
@ 2011-08-30 15:38 ` Adam Beneschan
  2011-08-30 16:42   ` Dmitry A. Kazakov
  2011-08-31 16:39   ` Adam Beneschan
  2011-08-31 18:08 ` Robert A Duff
  2 siblings, 2 replies; 21+ messages in thread
From: Adam Beneschan @ 2011-08-30 15:38 UTC (permalink / raw)


On Aug 30, 6:22 am, Marc C <mc.provisio...@gmail.com> wrote:
> Saw this pop up in AdaCore's Developer Center notices:
>
> >[GNAT] Automatic deallocation of task upon termination
>
> >Monday August 29, 2011
>
> >If Unchecked_Deallocation is called on a non-terminated task (which was previously a no-op),
> >the task is now marked to be freed automatically when it terminates.
>
> [http://www.adacore.com/2011/08/29/NF-65-H911-007-gnat/]
>
> This *looks* to me like one could dynamically allocate a task instance
> and then immediately free it with an instantiation of
> Unchecked_Deallocation, yet the task would continue to function
> normally until it terminates.
>
> This seems rather a stretch to me, is there more to this than this
> brief summary lets on?

I think this is right---the task continues to function until it
terminates.  The only way to get a task to stop executing before it
completes is to abort it (via an abort statement, or other semantics
that cause an abort---see 9.8).  An Unchecked_Deallocation instance
finalizes the task object, but the semantics of finalization don't
involve aborting.  I'm having a bit of difficulty figuring out from
the RM what the exact semantics of finalizing an unterminated task
object are, but I'm pretty sure that aborting the task is not one of
them.  (Note that this applies only to tasks without discriminants.
If the task has discriminants, freeing it is an
error---13.11.2(11ff).)

                                -- Adam



                               -- Adam





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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 15:38 ` Adam Beneschan
@ 2011-08-30 16:42   ` Dmitry A. Kazakov
  2011-08-30 18:57     ` Niklas Holsti
  2011-08-31 16:39   ` Adam Beneschan
  1 sibling, 1 reply; 21+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-30 16:42 UTC (permalink / raw)


On Tue, 30 Aug 2011 08:38:52 -0700 (PDT), Adam Beneschan wrote:

>  I'm having a bit of difficulty figuring out from
> the RM what the exact semantics of finalizing an unterminated task
> object are, but I'm pretty sure that aborting the task is not one of
> them.  (Note that this applies only to tasks without discriminants.
> If the task has discriminants, freeing it is an
> error---13.11.2(11ff).)

What is the difference? Is it an attempt to have freed tasks running
further? Or an attempt to construct a race condition, e.g. when the task
being freed has an open terminate alternative or else has been accepted a
rendezvous and now is going down? 

Considering this standard pattern:

type Object;
task type Worker (Self : not null access Object'Class) is
   entry Shut_Down;
end Worker;
type Worker_Ptr is access Worker;
type Object is new Ada.Finalization.Limited_Controlled with record
   Worker : Worker_Ptr;
end Object;
overriding procedure Finalize (This : in out Object);

Now the following is a race with a bounded error:

procedure Finalize (This : in out Object) is
   procedure Free is new Ada.Unchecked_Deallocation (...);
begin
   if This.Worker /= null then
      This.Worker.Shut_Down;
      Free (This.Worker);
   end if;
end Finalize;

which shall be rewritten as:

procedure Finalize (This : in out Object) is
   procedure Free is new Ada.Unchecked_Deallocation (...);
begin
   if This.Worker /= null then
      This.Worker.Shut_Down;
      while not Worker'Terminated loop
         delay 0.1;
      end loop;
      Free (This.Worker);
   end if;
end Finalize;

Is it so?

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



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 16:42   ` Dmitry A. Kazakov
@ 2011-08-30 18:57     ` Niklas Holsti
  2011-08-30 19:23       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 21+ messages in thread
From: Niklas Holsti @ 2011-08-30 18:57 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Tue, 30 Aug 2011 08:38:52 -0700 (PDT), Adam Beneschan wrote:
> 
>>  I'm having a bit of difficulty figuring out from
>> the RM what the exact semantics of finalizing an unterminated task
>> object are, but I'm pretty sure that aborting the task is not one of
>> them.  (Note that this applies only to tasks without discriminants.
>> If the task has discriminants, freeing it is an
>> error---13.11.2(11ff).)
> 
> What is the difference? Is it an attempt to have freed tasks running
> further? Or an attempt to construct a race condition, e.g. when the task
> being freed has an open terminate alternative or else has been accepted a
> rendezvous and now is going down? 

I assume that by "it" above, Dmitry is referring to the AdaCore notice 
about a change in the way Unchecked_Deallocation works in on tasks in 
GNAT, as quoted by Marc in his original post:

"If Unchecked_Deallocation is called on a non-terminated task (which was 
previously a no-op), the task is now marked to be freed automatically 
when it terminates."

It seems to me that the new behaviour is more useful than the old behaviour.

> Considering this standard pattern:
> 
> type Object;
> task type Worker (Self : not null access Object'Class) is
>    entry Shut_Down;
> end Worker;
> type Worker_Ptr is access Worker;
> type Object is new Ada.Finalization.Limited_Controlled with record
>    Worker : Worker_Ptr;
> end Object;
> overriding procedure Finalize (This : in out Object);

(I don't think that the use of a controlled type is central to the 
example. Am I wrong, Dmitry?)

> Now the following is a race with a bounded error:

As I understand it, there was a race under the old behaviour, but not 
under the new behaviour.

> procedure Finalize (This : in out Object) is
>    procedure Free is new Ada.Unchecked_Deallocation (...);
> begin
>    if This.Worker /= null then
>       This.Worker.Shut_Down;
>       Free (This.Worker);

With the old behaviour of Unchecked_Deallocation, the effect of this 
Free call depended on the state of This.Worker: if the task was not yet 
terminated, Free had no effect; if the task was terminated, Free 
deallocated the task object.

With the new behaviour, the task object is always deallocated, either by 
  the Free call (if the task is already terminated at that time) or by 
the RTS when the task terminates later, after the Free call.

>    end if;
> end Finalize;
> 
> which shall be rewritten as:

Under the old behavior, this rewrite was necessary to ensure that the 
task is deallocated. Under the new behaviour, it is not necessary. As I 
understand it.

> procedure Finalize (This : in out Object) is
>    procedure Free is new Ada.Unchecked_Deallocation (...);
> begin
>    if This.Worker /= null then
>       This.Worker.Shut_Down;
>       while not Worker'Terminated loop
>          delay 0.1;
>       end loop;
>       Free (This.Worker);
>    end if;
> end Finalize;

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 18:57     ` Niklas Holsti
@ 2011-08-30 19:23       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 21+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-30 19:23 UTC (permalink / raw)


On Tue, 30 Aug 2011 21:57:54 +0300, Niklas Holsti wrote:

> Dmitry A. Kazakov wrote:
>> On Tue, 30 Aug 2011 08:38:52 -0700 (PDT), Adam Beneschan wrote:
>> 
>>>  I'm having a bit of difficulty figuring out from
>>> the RM what the exact semantics of finalizing an unterminated task
>>> object are, but I'm pretty sure that aborting the task is not one of
>>> them.  (Note that this applies only to tasks without discriminants.
>>> If the task has discriminants, freeing it is an
>>> error---13.11.2(11ff).)
>> 
>> What is the difference? Is it an attempt to have freed tasks running
>> further? Or an attempt to construct a race condition, e.g. when the task
>> being freed has an open terminate alternative or else has been accepted a
>> rendezvous and now is going down? 
> 
> I assume that by "it" above, Dmitry is referring to the AdaCore notice 
> about a change in the way Unchecked_Deallocation works in on tasks in 
> GNAT, as quoted by Marc in his original post:

No, I meant the rationale behind ARM 13.11.2(11), which looks dubious to
me.

> "If Unchecked_Deallocation is called on a non-terminated task (which was 
> previously a no-op), the task is now marked to be freed automatically 
> when it terminates."
> 
> It seems to me that the new behaviour is more useful than the old behaviour.

Maybe. But it is unclear if it is consistent with the expectations of a
naive user. Which is: Unchecked_Deallocation awaits for the task
termination and then frees whatever memory the task is using.

>> Considering this standard pattern:
>> 
>> type Object;
>> task type Worker (Self : not null access Object'Class) is
>>    entry Shut_Down;
>> end Worker;
>> type Worker_Ptr is access Worker;
>> type Object is new Ada.Finalization.Limited_Controlled with record
>>    Worker : Worker_Ptr;
>> end Object;
>> overriding procedure Finalize (This : in out Object);
> 
> (I don't think that the use of a controlled type is central to the 
> example. Am I wrong, Dmitry?)

It is the most common case when a task has a discriminant. Since task as a
component is a non-starter, the only work-around would be a controlled type
removing its access-to-task component from Finalize.

>> Now the following is a race with a bounded error:
> 
> As I understand it, there was a race under the old behaviour, but not 
> under the new behaviour.

Well, it could be read as if the choice offered by ARM 13.11.2(12) was
taken. Though according to ARM, it is still a bounded error, and maybe even
worse than that (see the scenario below).

>> procedure Finalize (This : in out Object) is
>>    procedure Free is new Ada.Unchecked_Deallocation (...);
>> begin
>>    if This.Worker /= null then
>>       This.Worker.Shut_Down;
>>       Free (This.Worker);
> 
> With the old behaviour of Unchecked_Deallocation, the effect of this 
> Free call depended on the state of This.Worker: if the task was not yet 
> terminated, Free had no effect; if the task was terminated, Free 
> deallocated the task object.
> 
> With the new behaviour, the task object is always deallocated, either by 
>   the Free call (if the task is already terminated at that time) or by 
> the RTS when the task terminates later, after the Free call.

This is unclear. Because if Free is not blocked, the Object's Finalize
continues, possibly ends (and then the object is freed), while the task is
still running and possibly accessing the object through its discriminant.
This kind of error is unbounded in contradiction to ARM 13.11.2(11). It
would be rather catastrophic behavior.

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



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 15:38 ` Adam Beneschan
  2011-08-30 16:42   ` Dmitry A. Kazakov
@ 2011-08-31 16:39   ` Adam Beneschan
  2011-08-31 18:21     ` Robert A Duff
  2011-08-31 20:30     ` J-P. Rosen
  1 sibling, 2 replies; 21+ messages in thread
From: Adam Beneschan @ 2011-08-31 16:39 UTC (permalink / raw)


On Aug 30, 8:38 am, Adam Beneschan <a...@irvine.com> wrote:

> I think this is right---the task continues to function until it
> terminates.  The only way to get a task to stop executing before it
> completes is to abort it (via an abort statement, or other semantics
> that cause an abort---see 9.8).  An Unchecked_Deallocation instance
> finalizes the task object, but the semantics of finalization don't
> involve aborting.  I'm having a bit of difficulty figuring out from
> the RM what the exact semantics of finalizing an unterminated task
> object are, but I'm pretty sure that aborting the task is not one of
> them.

Actually, I just found this in the Ada 83 manual (13.10.1(8)):

"If X designates a task object, the call FREE(X) [where FREE is an
instance of Unchecked_Deallocation] has no effect on the task
desginated by the value of the task object.  The same holds for any
subcomponent of the object designated by X, if this subcomponent is a
task object."

This language got dropped in Ada 95, but I think it was intended that
these still be the semantics, for a task without discriminants (Ada 83
did not allow task discriminants).  I'm not sure why the language was
omitted; it could have just been inadvertent (I've seen one or two
other cases where RM83 language got lost and left some things
undefined that should have been defined), or the authors could have
felt that it was no longer necessary because of other wording changes,
particularly those dealing with finalization.  The latter could be
correct, although I've been having trouble finding RM language that
made it clear that this was supposed to happen.  The current RM does
say that "if the object being freed contains tasks, the object might
not be deallocated", but this doesn't clearly say anything about what
happens to the task.

One thing that bothers me a bit, although I don't know if it bothers
me enough to request an RM change: 13.11.2(10) says that after
Free(X), the designated object and its subcomponents no longer exist.
9.1(15-18) says that the content of a task object includes entry
queues for the task.  I'm willing to accept that there is a
distinction between a task object and a task (or a task execution),
but if the task object no longer exists, does that mean that the entry
queues that it contains no longer exist, and that therefore if another
task Y was waiting on X.all's entry when X was freed, so that the
entry queue on which Y was sitting no longer exists, does Y's entry
call get cancelled?  Again, I don't think this is the intent, but I'm
not sure.

                           -- Adam



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 13:22 Delayed deallocation of non-terminated task in Gnat? Marc C
  2011-08-30 15:20 ` Dmitry A. Kazakov
  2011-08-30 15:38 ` Adam Beneschan
@ 2011-08-31 18:08 ` Robert A Duff
  2 siblings, 0 replies; 21+ messages in thread
From: Robert A Duff @ 2011-08-31 18:08 UTC (permalink / raw)


Marc C <mc.provisional@gmail.com> writes:

> This *looks* to me like one could dynamically allocate a task instance
> and then immediately free it with an instantiation of
> Unchecked_Deallocation, yet the task would continue to function
> normally until it terminates.

Yes.  Ada semantics requires that if you call Unchecked_Deallocation
on an object that contains running tasks, the tasks keep running.

In the old version of GNAT, U_D would say "Is the task terminated?
If so, free up its resources.  If not, do nothing."  So it could
leak memory.

The new version of GNAT is better: "Is the task terminated?
If so, free up its resources.  If not, cause its resources
to be freed up when it does terminate."

But you have to be careful:  Like any U_D, you can have
dangling pointers.

- Bob



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-30 15:20 ` Dmitry A. Kazakov
@ 2011-08-31 18:12   ` Robert A Duff
  2011-08-31 19:23     ` Dmitry A. Kazakov
  2011-08-31 20:25     ` J-P. Rosen
  0 siblings, 2 replies; 21+ messages in thread
From: Robert A Duff @ 2011-08-31 18:12 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> Does it mean that Unchecked_Deallocation won't wait for the task to
> terminate? That would be surprising.

U_D does not wait for tasks to terminate.  That's always been
the case.

I consider it a flaw in Ada that there's no general-purpose
way to block waiting for the termination of a task, or a group of
tasks.  I'm not sure U_D should be that feature, though,
because then it would only work for access-to-task(s).

- Bob



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 16:39   ` Adam Beneschan
@ 2011-08-31 18:21     ` Robert A Duff
  2011-08-31 23:28       ` Adam Beneschan
  2011-08-31 20:30     ` J-P. Rosen
  1 sibling, 1 reply; 21+ messages in thread
From: Robert A Duff @ 2011-08-31 18:21 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> Actually, I just found this in the Ada 83 manual (13.10.1(8)):
>
> "If X designates a task object, the call FREE(X) [where FREE is an
> instance of Unchecked_Deallocation] has no effect on the task
> desginated by the value of the task object.  The same holds for any
> subcomponent of the object designated by X, if this subcomponent is a
> task object."
>
> This language got dropped in Ada 95, but I think it was intended that
> these still be the semantics, for a task without discriminants (Ada 83
> did not allow task discriminants).  I'm not sure why the language was
> omitted; ...

It might have to do with the fact that task values don't formally
"designate" anymore.  Anyway, it doesn't need to say anything.
If it doesn't say anything happens to the task, then nothing
happens -- it just keeps running.  It doesn't say U_D waits
for it to terminate.  It doesn't say U_D aborts it.  It doesn't
say that U_D should set all variables to 17.  So none of these
things happen.

> One thing that bothers me a bit, although I don't know if it bothers
> me enough to request an RM change:

I suggestion you refrain.  ;-)  This sort of nitpicking is just
a waste of time for the ARG.  Any wording change wouldn't affect
the behavior of any programmer, nor any implementer, so why
bother?

- Bob



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 18:12   ` Robert A Duff
@ 2011-08-31 19:23     ` Dmitry A. Kazakov
  2011-08-31 20:58       ` Robert A Duff
  2011-08-31 20:25     ` J-P. Rosen
  1 sibling, 1 reply; 21+ messages in thread
From: Dmitry A. Kazakov @ 2011-08-31 19:23 UTC (permalink / raw)


On Wed, 31 Aug 2011 14:12:26 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> Does it mean that Unchecked_Deallocation won't wait for the task to
>> terminate? That would be surprising.
> 
> U_D does not wait for tasks to terminate.  That's always been
> the case.
> 
> I consider it a flaw in Ada that there's no general-purpose
> way to block waiting for the termination of a task,

Yes. If there exist terminate alternative, it must have a corresponding
entry. E.g.

   T'Terminate

could denote the terminate entry of the task T. The semantics of the
rendezvous to T'Terminate is obvious, upon completion the callee is
terminated. It would be simple to introduce, IMO.

Also the terminate alternative should allow a handled sequence of
statements, e.g.

   select
       ...
   or terminate [do ... end terminate];
      ...
   end select;

> or a group of tasks.

There is no rendezvous to multiple tasks or calls to multiple entry points
(of several protected objects). It could be useful but the semantics is
unclear.

> I'm not sure U_D should be that feature, though,
> because then it would only work for access-to-task(s).

It certainly should. The behavior of an object may not depend on the way it
was allocated. Since deallocation of a task on the stack is effectively
blocking, so its deallocation using Unchecked_Deallocation should be. I see
no use in a non-blocking Unchecked_Deallocation.

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



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 18:12   ` Robert A Duff
  2011-08-31 19:23     ` Dmitry A. Kazakov
@ 2011-08-31 20:25     ` J-P. Rosen
  2011-08-31 21:09       ` Robert A Duff
  1 sibling, 1 reply; 21+ messages in thread
From: J-P. Rosen @ 2011-08-31 20:25 UTC (permalink / raw)


Le 31/08/2011 20:12, Robert A Duff a �crit :
> I consider it a flaw in Ada that there's no general-purpose
> way to block waiting for the termination of a task.
> 
With some cooperation of the other task...

Declare in the waited task an entry (Wait_For_Terminate) which is never
accepted. The waiting task calls the entry, and gets Tasking_Error when
the waited task terminates (for whatever reason).

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Adalog a d�m�nag� / Adalog has moved:
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 16:39   ` Adam Beneschan
  2011-08-31 18:21     ` Robert A Duff
@ 2011-08-31 20:30     ` J-P. Rosen
  2011-08-31 22:36       ` Adam Beneschan
  1 sibling, 1 reply; 21+ messages in thread
From: J-P. Rosen @ 2011-08-31 20:30 UTC (permalink / raw)


Le 31/08/2011 18:39, Adam Beneschan a �crit :
> One thing that bothers me a bit, although I don't know if it bothers
> me enough to request an RM change: 13.11.2(10) says that after
> Free(X), the designated object and its subcomponents no longer exist.
> 9.1(15-18) says that the content of a task object includes entry
> queues for the task.  I'm willing to accept that there is a
> distinction between a task object and a task (or a task execution),
> but if the task object no longer exists, does that mean that the entry
> queues that it contains no longer exist, and that therefore if another
> task Y was waiting on X.all's entry when X was freed, so that the
> entry queue on which Y was sitting no longer exists, does Y's entry
> call get cancelled?  Again, I don't think this is the intent, but I'm
> not sure.
> 
As soon as a task iscompleted, all waiting tasks receive Tasking_Error.
Since the space is (hopefully!) deallocated after the task is completed
(and even terminated), there is no problem.

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Adalog a d�m�nag� / Adalog has moved:
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 19:23     ` Dmitry A. Kazakov
@ 2011-08-31 20:58       ` Robert A Duff
  2011-08-31 21:16         ` Jeffrey Carter
  0 siblings, 1 reply; 21+ messages in thread
From: Robert A Duff @ 2011-08-31 20:58 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> Yes. If there exist terminate alternative, it must have a corresponding
> entry. E.g.
>
>    T'Terminate
>
> could denote the terminate entry of the task T. The semantics of the
> rendezvous to T'Terminate is obvious, upon completion the callee is
> terminated. It would be simple to introduce, IMO.

Simple to introduce from a semantics point of view, and useful,
but rather tricky to implement, for the same reasons that the
feature we're discussing (avoiding the storage leak) is tricky.
If a task itself notices that it is about to terminate,
and therefore frees resources (the task control block,
the task stack), it is running while it's doing that stuff,
and it's tricky to make sure it doesn't use those resources
after they're freed.  E.g., the free wanted to defer/undefer
aborts, which involves touching the task control block,
which is being freed!  We figured out how to do it, and it
wasn't a lot of code, but it was very subtle code.

>> or a group of tasks.
>
> There is no rendezvous to multiple tasks or calls to multiple entry points
> (of several protected objects).

That was proposed for Ada 9X.

>... It could be useful but the semantics is
> unclear.

As I recall, there was both "and" and "or" semantics.  So in the context
of termination, that would give you "wait until all these tasks are
terminated", and "wait until one of these tasks is terminated (and tell
me which one)".

>> I'm not sure U_D should be that feature, though,
>> because then it would only work for access-to-task(s).
>
> It certainly should. The behavior of an object may not depend on the way it
> was allocated. Since deallocation of a task on the stack is effectively
> blocking, so its deallocation using Unchecked_Deallocation should be. I see
> no use in a non-blocking Unchecked_Deallocation.

Maybe you're right, I'm not sure.  I think it does make sense to fire up
a task, and have it get freed on termination, with no particular other
task waiting for that termination.  The U_D you want, that waits for
termination, can be written in terms of the mythical "await termination"
primitive we discussed above, and the existing Ada U_D that does not
wait.

- Bob



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 20:25     ` J-P. Rosen
@ 2011-08-31 21:09       ` Robert A Duff
  2011-08-31 21:53         ` Simon Wright
  0 siblings, 1 reply; 21+ messages in thread
From: Robert A Duff @ 2011-08-31 21:09 UTC (permalink / raw)


"J-P. Rosen" <rosen@adalog.fr> writes:

> Le 31/08/2011 20:12, Robert A Duff a �crit :
>> I consider it a flaw in Ada that there's no general-purpose
>> way to block waiting for the termination of a task.
>> 
> With some cooperation of the other task...
>
> Declare in the waited task an entry (Wait_For_Terminate) which is never
> accepted. The waiting task calls the entry, and gets Tasking_Error when
> the waited task terminates (for whatever reason).

We thought of that while implementing the feature that started this
thread.  Unfortunately, it doesn't quite work.  The Tasking_Error is
raised when the task is completed, so at the time T_E is handled, the
other task could still be going about its business doing finalization.
And even if there's no user-level finalization involved, there's still
some stuff going on in the run-time system between completion and
termination.  So there's an inherent race condition here.

What I claim is missing from Ada (and is hard to implement) is a feature
that blocks a task until some other task(s) is/are really and truly
terminated, and won't execute a single 'nother instruction.

You can loop, checking 'Terminated, with a delay.  But the delay is
guaranteed to be either too long or too short -- most likely both.  The
feature we're talking about was implemented because there was such a
loop, and it was causing an AdaCore customer's program (with thousands
of dynamically allocated tasks) to take half an hour.  After
implementing this feature, and removing the loop-with-delay, it took a
few seconds.

- Bob



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 20:58       ` Robert A Duff
@ 2011-08-31 21:16         ` Jeffrey Carter
  0 siblings, 0 replies; 21+ messages in thread
From: Jeffrey Carter @ 2011-08-31 21:16 UTC (permalink / raw)


On 08/31/2011 01:58 PM, Robert A Duff wrote:
> "Dmitry A. Kazakov"<mailbox@dmitry-kazakov.de>  writes:
>
>> There is no rendezvous to multiple tasks or calls to multiple entry points
>> (of several protected objects).
>
> That was proposed for Ada 9X.

One can do

select
    Entry_Call_1;
then abort
    Entry_Call_2;
end select;

and

select
    Entry_Call_1;
then abort
    select
       Entry_Call_2;
    then abort
       Entry_Call_3;
    end select;
end select;

and so on forever, as far as I can tell. This has the effect of waiting for one 
of multiple entry calls.

-- 
Jeff Carter
"You a big nose have it."
Never Give a Sucker an Even Break
107



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 21:09       ` Robert A Duff
@ 2011-08-31 21:53         ` Simon Wright
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Wright @ 2011-08-31 21:53 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> writes:

> You can loop, checking 'Terminated, with a delay.  But the delay is
> guaranteed to be either too long or too short -- most likely both.
> The feature we're talking about was implemented because there was such
> a loop, and it was causing an AdaCore customer's program (with
> thousands of dynamically allocated tasks) to take half an hour.  After
> implementing this feature, and removing the loop-with-delay, it took a
> few seconds.

We couldn't afford to wait, so once we discovered the leak we arranged
that all tasks to be deleted were aborted and placed on a special list;
a low-priority task did the loop-with-delay-until-terminated and then
the U_D.

   generic
      type Task_Type (<>) is limited private;
      --  The class's task type (T).
      type Task_Type_P is access Task_Type;
      --  The class's pointer-to-task (T_P).
      with function Is_Terminated (It : Task_Type_P) return Boolean;
      --  We can't say that Task_Type is actually a task, so we can't use
      --  'Identity.
   package ColdFrame.Task_Deletion_G is
      procedure Free (It : Task_Type_P);
      --  Puts It on the queue of tasks to be freed.
   private

(a) all the instantiations and calls of this code were autogenerated, so
the developer pain was minimised; 

(b) we didn't have many task deletions (mainly on network disconnects).



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 20:30     ` J-P. Rosen
@ 2011-08-31 22:36       ` Adam Beneschan
  2011-09-01  5:24         ` J-P. Rosen
  0 siblings, 1 reply; 21+ messages in thread
From: Adam Beneschan @ 2011-08-31 22:36 UTC (permalink / raw)


On Aug 31, 1:30 pm, "J-P. Rosen" <ro...@adalog.fr> wrote:
> Le 31/08/2011 18:39, Adam Beneschan a écrit :> One thing that bothers me a bit, although I don't know if it bothers
> > me enough to request an RM change: 13.11.2(10) says that after
> > Free(X), the designated object and its subcomponents no longer exist.
> > 9.1(15-18) says that the content of a task object includes entry
> > queues for the task.  I'm willing to accept that there is a
> > distinction between a task object and a task (or a task execution),
> > but if the task object no longer exists, does that mean that the entry
> > queues that it contains no longer exist, and that therefore if another
> > task Y was waiting on X.all's entry when X was freed, so that the
> > entry queue on which Y was sitting no longer exists, does Y's entry
> > call get cancelled?  Again, I don't think this is the intent, but I'm
> > not sure.
>
> As soon as a task iscompleted, all waiting tasks receive Tasking_Error.
> Since the space is (hopefully!) deallocated after the task is completed
> (and even terminated), there is no problem.

But I'm not talking about a task being completed.  It's pretty clear
that it's possible to use Unchecked_Deallocation on an object that
contains an access to a task, and this Unchecked_Deallocation can
complete, without the task being completed.  But this means that the
task *object* (which isn't the same as a task, I think) ceases to
exist, even though the task still hasn't completed; and a literal (but
possibly absurd) reading of the RM would mean that the task's entry
queues no longer exist (even though the task still hasn't completed),
leading to questions about what happens to tasks that are already on
those queues.

                       -- Adam




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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 18:21     ` Robert A Duff
@ 2011-08-31 23:28       ` Adam Beneschan
  2011-09-01 11:58         ` Robert A Duff
  0 siblings, 1 reply; 21+ messages in thread
From: Adam Beneschan @ 2011-08-31 23:28 UTC (permalink / raw)


On Aug 31, 11:21 am, Robert A Duff <bobd...@shell01.TheWorld.com>
wrote:
> Adam Beneschan <a...@irvine.com> writes:
> > Actually, I just found this in the Ada 83 manual (13.10.1(8)):
>
> > "If X designates a task object, the call FREE(X) [where FREE is an
> > instance of Unchecked_Deallocation] has no effect on the task
> > desginated by the value of the task object.  The same holds for any
> > subcomponent of the object designated by X, if this subcomponent is a
> > task object."
>
> > This language got dropped in Ada 95, but I think it was intended that
> > these still be the semantics, for a task without discriminants (Ada 83
> > did not allow task discriminants).  I'm not sure why the language was
> > omitted; ...
>
> It might have to do with the fact that task values don't formally
> "designate" anymore.

But access objects do, and in the RM83 paragraph, X is an access
object.

> Anyway, it doesn't need to say anything.
> If it doesn't say anything happens to the task, then nothing
> happens -- it just keeps running.  It doesn't say U_D waits
> for it to terminate.  It doesn't say U_D aborts it.  It doesn't
> say that U_D should set all variables to 17.  So none of these
> things happen.

Perhaps.  But the fact that we've seen two different incorrect
assumptions about what this does to the task (one thought the task
would immediately terminate, as if it were aborted, and another
thought it would wait for the task to terminate) means that maybe it
would be helpful to add the RM83 language back in (for
nondiscriminated tasks).  By the way, the only way one can know that
the RM doesn't say anything happens to the task is to read and fully
understand the entire RM, since otherwise one never knows what other
semantics there are elsewhere in the RM that may answer the question
or that may combine to give an answer to the question.  I studied
7.6.1 and several sections in Chapter 9 pretty thoroughly before
concluding that the RM didn't say that anything happened to the task.
And that's not helpful to someone who's consulting the RM to try to
find out how things work.  Keep in mind that the R in RM does stand
for something.

                          -- Adam



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 22:36       ` Adam Beneschan
@ 2011-09-01  5:24         ` J-P. Rosen
  0 siblings, 0 replies; 21+ messages in thread
From: J-P. Rosen @ 2011-09-01  5:24 UTC (permalink / raw)


Le 01/09/2011 00:36, Adam Beneschan a �crit :
> But I'm not talking about a task being completed.  It's pretty clear
> that it's possible to use Unchecked_Deallocation on an object that
> contains an access to a task, and this Unchecked_Deallocation can
> complete, without the task being completed.  But this means that the
> task *object* (which isn't the same as a task, I think) ceases to
> exist, even though the task still hasn't completed; and a literal (but
> possibly absurd) reading of the RM would mean that the task's entry
> queues no longer exist (even though the task still hasn't completed),
> leading to questions about what happens to tasks that are already on
> those queues.
> 
TBH, I didn't even think that anybody (human, RM, or implementation)
would even consider freeing part of a task's space before the task is
completed ;-)

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Adalog a d�m�nag� / Adalog has moved:
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00



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

* Re: Delayed deallocation of non-terminated task in Gnat?
  2011-08-31 23:28       ` Adam Beneschan
@ 2011-09-01 11:58         ` Robert A Duff
  0 siblings, 0 replies; 21+ messages in thread
From: Robert A Duff @ 2011-09-01 11:58 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> On Aug 31, 11:21�am, Robert A Duff <bobd...@shell01.TheWorld.com>
> wrote:
>> Adam Beneschan <a...@irvine.com> writes:
>> > Actually, I just found this in the Ada 83 manual (13.10.1(8)):
>>
>> > "If X designates a task object, the call FREE(X) [where FREE is an
>> > instance of Unchecked_Deallocation] has no effect on the task
>> > desginated by the value of the task object. �The same holds for any
>> > subcomponent of the object designated by X, if this subcomponent is a
>> > task object."
>>
>> > This language got dropped in Ada 95, but I think it was intended that
>> > these still be the semantics, for a task without discriminants (Ada 83
>> > did not allow task discriminants). �I'm not sure why the language was
>> > omitted; ...
>>
>> It might have to do with the fact that task values don't formally
>> "designate" anymore.
>
> But access objects do, and in the RM83 paragraph, X is an access
> object.

Right, but there are two "designate" in the Ada 83 wording.
I was referring to the second one.

In Ada 83, a task object contains a task value, which is a pointer
that designates a task.  So if you have an access-to-task object,
it's value designates a task object whose value designates the task.

>...By the way, the only way one can know that
> the RM doesn't say anything happens to the task is to read and fully
> understand the entire RM, ...

Yeah, that's a problem.

- Bob



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

end of thread, other threads:[~2011-09-01 11:58 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-30 13:22 Delayed deallocation of non-terminated task in Gnat? Marc C
2011-08-30 15:20 ` Dmitry A. Kazakov
2011-08-31 18:12   ` Robert A Duff
2011-08-31 19:23     ` Dmitry A. Kazakov
2011-08-31 20:58       ` Robert A Duff
2011-08-31 21:16         ` Jeffrey Carter
2011-08-31 20:25     ` J-P. Rosen
2011-08-31 21:09       ` Robert A Duff
2011-08-31 21:53         ` Simon Wright
2011-08-30 15:38 ` Adam Beneschan
2011-08-30 16:42   ` Dmitry A. Kazakov
2011-08-30 18:57     ` Niklas Holsti
2011-08-30 19:23       ` Dmitry A. Kazakov
2011-08-31 16:39   ` Adam Beneschan
2011-08-31 18:21     ` Robert A Duff
2011-08-31 23:28       ` Adam Beneschan
2011-09-01 11:58         ` Robert A Duff
2011-08-31 20:30     ` J-P. Rosen
2011-08-31 22:36       ` Adam Beneschan
2011-09-01  5:24         ` J-P. Rosen
2011-08-31 18:08 ` Robert A Duff

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