comp.lang.ada
 help / color / mirror / Atom feed
* Deallocating Task objects
@ 1997-02-15  0:00 Jonas Nygren
  1997-02-15  0:00 ` Robert Dewar
  1997-02-17  0:00 ` Mats Weber
  0 siblings, 2 replies; 8+ messages in thread
From: Jonas Nygren @ 1997-02-15  0:00 UTC (permalink / raw)




I sent out a question to c.l.a about how to reclaim memory for tasks
that are dynamically allocated. Since then I have been trying to find 
some 'nice' way of doing this.

I have identified one sentence in the Ada RM that seems to provide
some sort of automatic storage reclamation. The sentence is found in 
13.11(18) and reads:

"If Storage_Size is specified for an access type, then the Storage_Size 
 of this pool is at least that requested, and the storage for the pool 
 is reclaimed when the master containing the declaration of the access 
 type is left."

This seems to provide some sort of 'garbage collection'. One have
to give an upper bound on the number of allocatable objects but this is
quite acceptable for my code.

I wonder if somebody can confirm that my interpretation of this sentence
is correct. Below I have attached a small tasking example with one
Main_Task that dynamically allocates Sub_Tasks and I want to be absolutely 
sure that the storage used for the Sub_Tasks have been reclaimed when the
Main_Task instance, A_Main_Task, goes out of scope.

Have I interpreted the 13.11(18) sentence correctly? Is the construct 
portable between different Ada compilers?

/jonas

PS of course I could have defined an array of Sub_Tasks instead but then
   there would have been the added complexity of synchronizing the
Main_Task's
   stack size with the number of allocated Sub_Tasks. DS

PPS I have tried this with Gnat 3.09 for NT and Win95 and it will only
handle
    a maximum of 57 Sub_Tasks. With 58, or more, Sub_Tasks it will just
hang 
    in the allocator, without any errors. I will report this bug to ACT.
DDS

-- code follows

with Text_IO;
procedure Test is
   task type Main_Task (Max_Sub_Tasks : Positive);

   task body Main_Task is

      task type Sub_Task is
         entry Dummy;
      end Sub_Task;

      type Sub_Task_Ref is access Sub_Task;
      for Sub_Task_Ref'Storage_Size use Max_Sub_Tasks * Sub_Task'Size; --
13.11(18)

      task body Sub_Task is
      begin
         loop
            select
               accept Dummy;
            or
               terminate;
            end select;
         end loop;
      end Sub_Task;

      A_Sub_Task : Sub_Task_Ref;
   begin
      for I in 1..Max_Sub_Tasks loop
         A_Sub_Task := new Sub_Task;
	  Text_IO.Put_Line(Integer'Image(I));
      end loop;

      delay 1.0;
   end Main_Task;
begin
   declare
      A_Main_Task : Main_Task(1000);
   begin
      null;
   end;
   -- at this point all storage allocated for Sub_Task objects
   -- in A_Main_Task will have been reclaimed
end Test;





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

* Re: Deallocating Task objects
  1997-02-15  0:00 Deallocating Task objects Jonas Nygren
@ 1997-02-15  0:00 ` Robert Dewar
  1997-02-17  0:00 ` Mats Weber
  1 sibling, 0 replies; 8+ messages in thread
From: Robert Dewar @ 1997-02-15  0:00 UTC (permalink / raw)



Jonas asks

<<I wonder if somebody can confirm that my interpretation of this sentence
is correct. Below I have attached a small tasking example with one
Main_Task that dynamically allocates Sub_Tasks and I want to be absolutely
sure that the storage used for the Sub_Tasks have been reclaimed when the
Main_Task instance, A_Main_Task, goes out of scope.
>>

I would not call this garbage collectoin in any sense. it is more like
the PL/1 area concept. Note that you can trivially do something like
this yourself by using the storage pools mechanism. Indeed the way this
is accomplished at least in GNAt is precisely by using the storage pools
mechanism.





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

* Re: Deallocating Task objects
  1997-02-15  0:00 Deallocating Task objects Jonas Nygren
  1997-02-15  0:00 ` Robert Dewar
@ 1997-02-17  0:00 ` Mats Weber
  1997-02-18  0:00   ` Robert L. Spooner
  1 sibling, 1 reply; 8+ messages in thread
From: Mats Weber @ 1997-02-17  0:00 UTC (permalink / raw)



Jonas Nygren wrote:
> I wonder if somebody can confirm that my interpretation of this sentence
> is correct. Below I have attached a small tasking example with one
> Main_Task that dynamically allocates Sub_Tasks and I want to be absolutely
> sure that the storage used for the Sub_Tasks have been reclaimed when the
> Main_Task instance, A_Main_Task, goes out of scope.
> 
> Have I interpreted the 13.11(18) sentence correctly? Is the construct
> portable between different Ada compilers?

No, the guarantee that the space occupied by the tasks is reclaimed is
not portable. On most systems, the size (as given by 'Size) of a task
object is 32 bits (the size of a pointer), and the task object is just a
pointer to memory that describes the task. What 13.11(18) guarantees is
that the space occupied by these pointers is reclamed, but not the space
occupied by the tasks themselves (i.e. their stack, etc.).

The approach the we are using for such cases is to have a free list for
each task type that is allocated dynamically. When such a task finishes
its work, it appends itself to this free list, and it can be reused
later when a new task is needed. We then terminate the tasks in the free
lists on program termination.

It was absulutely necessary to use this approach five years ago with DEC
Ada and Verdix Ada because these implementations always kept some memory
allocated for tasks pointed to by library-level access types. I don't
know if it's still required, but we continue using that approach because
it's not much extra work as we have a generic package that we
instantiate for this purpose, and it automatically gives us some
information on how many tasks of each type we dynamically allocate.




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

* Re: Deallocating Task objects
  1997-02-17  0:00 ` Mats Weber
@ 1997-02-18  0:00   ` Robert L. Spooner
  1997-02-18  0:00     ` Robert A Duff
  0 siblings, 1 reply; 8+ messages in thread
From: Robert L. Spooner @ 1997-02-18  0:00 UTC (permalink / raw)



Mats Weber wrote:
> 
> It was absulutely necessary to use this approach five years ago with DEC
> Ada and Verdix Ada because these implementations always kept some memory
> allocated for tasks pointed to by library-level access types. I don't
> know if it's still required, but we continue using that approach because
> it's not much extra work as we have a generic package that we
> instantiate for this purpose, and it automatically gives us some
> information on how many tasks of each type we dynamically allocate.

For Ada 83 some memory had to be kept so that the task attributes such
as 
T'terminated could be used.  I don't know enough about Ada (95) yet to
know 
if it is still necessary.
-- 
                               Robert L. Spooner
                        Registered Professional Engineer
                               Research Assistant
                        Guidance and Control Department

               Applied Research Laboratory        Phone: (814) 863-4120
               The Pennsylvania State University  FAX:   (814) 863-7843
               P. O. Box 30
               State College, PA 16804-0030       RLS19@psu.edu




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

* Re: Deallocating Task objects
  1997-02-18  0:00   ` Robert L. Spooner
@ 1997-02-18  0:00     ` Robert A Duff
  1997-02-18  0:00       ` Robert Dewar
  0 siblings, 1 reply; 8+ messages in thread
From: Robert A Duff @ 1997-02-18  0:00 UTC (permalink / raw)



In article <3309C668.7D8E@Sor.psu.edu>,
Robert L. Spooner <rls19@psu.edu> wrote:
>For Ada 83 some memory had to be kept so that the task attributes such
>as T'terminated could be used.  I don't know enough about Ada (95) yet
>to know if it is still necessary.

The case is where a function returns a task object that is local to the
function.  I believe there was an Ada 83 AI that "clarified" that this
case was erroneous, so that storage for the task could be deallocated
upon leaving the function.  (In the standards business, "clarified" is a
euphemism for "fixing a bug in the language".  ;-))  Unfortunately, this
fix was made after ACVC tests had already forced implementers to keep
that storage around.

In Ada 95, this case raises Program_Error.  The error can actually be
caught at compile time, except in some cases involving generics -- a
good compiler will warn at compile time.

See AARM-6.5(20.a-20.d, 24.a-24.b) for some discussion of this stuff.

- Bob




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

* Re: Deallocating Task objects
  1997-02-18  0:00     ` Robert A Duff
@ 1997-02-18  0:00       ` Robert Dewar
  1997-02-20  0:00         ` Norman H. Cohen
  0 siblings, 1 reply; 8+ messages in thread
From: Robert Dewar @ 1997-02-18  0:00 UTC (permalink / raw)



Bob Duff said

<<The case is where a function returns a task object that is local to the
function.  I believe there was an Ada 83 AI that "clarified" that this
case was erroneous, so that storage for the task could be deallocated
upon leaving the function.  (In the standards business, "clarified" is a
euphemism for "fixing a bug in the language".  ;-))  Unfortunately, this
fix was made after ACVC tests had already forced implementers to keep
that storage around.

In Ada 95, this case raises Program_Error.  The error can actually be
caught at compile time, except in some cases involving generics -- a
good compiler will warn at compile time.>>



The history is not quite right, and is interesting. The Ada 83 RM does
indeed imply (but a not entirely obvious chain of reasoning), that a
function can return a local task, and the caller can check if it is
terminated. 

Jean Pierre Rosen noticed this and considered it an obvious bug in the
design. Confident that the ARG would fix this, he submitted it as an
issue. Amazingly, the ARG voted that this behavior was intended and
must be required. The consequence is awful, the only reasonable
implementation is to keep tasks around much longer than is needed.

At the following meeting of WG9, Jean Ichbiah and I launched an energetic
attempt to convince WG9 that this was NOT one of the ARG decisions that
should be approved. We lost, largely because Ron Brender of Digital
announced that this could be implemented without any negative impact.
(An ironic claim, since in fact the way that Digital reacted to this
ruling, like other vendors, was to delay freeing of locally allocated
tasks in this situation.

The ACVC suite, in the business of enforcing ARG decisions, then produced
tests that required this to work (how any one could possibly think this
was useful is beyond me). Implentors dutifully implemented it (at least
in the case of Digital and Alsys, this was done simply by not freeing
tasks completely in this situation, causing an annoying storage leak).

Much later, the ARG visited this issue, and declared that this situation
was pathological, which meant that no compiler was expected to implement
it (I do not remember if it was formally declared erroneous or not, I
don't have my AI's with me right now). This meant that the test was
challengable, but in fact, to my memory it did not get challenged, since
this was late in the Ada 83 cycle.

Finally, it was fixed, in a rather nice and general way in Ada 95.

Anyone want to add to or amend this bit of history (trying to remember
things from this far back in detail is always a bit unreliable :-)






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

* Re: Deallocating Task objects
  1997-02-18  0:00       ` Robert Dewar
@ 1997-02-20  0:00         ` Norman H. Cohen
  1997-02-21  0:00           ` Robert Dewar
  0 siblings, 1 reply; 8+ messages in thread
From: Norman H. Cohen @ 1997-02-20  0:00 UTC (permalink / raw)



Robert Dewar wrote:

> Much later, the ARG visited this issue, and declared that this situation
> was pathological, which meant that no compiler was expected to implement
> it (I do not remember if it was formally declared erroneous or not, I
> don't have my AI's with me right now). This meant that the test was
> challengable, but in fact, to my memory it did not get challenged, since
> this was late in the Ada 83 cycle.

It was not declared erroneous in Ada 83.  The ARG defined a new AI
category, "pathological", which said that the question at hand had
nothing to do with anything that could ever be useful in a real program,
and that even if the language gave a definite answer to the question, it
was not useful to write an ACVC test that would force implementors to
degrade their code to conform to that answer.  The later AI simply
reclassified the earlier AI from "binding interpretation" to
"pathological", meaning "Yes, a terminated task can be returned outside
of its master, but it's utterly useless to write a program that does
this, so we don't care if it works right, and we don't want implementors
degrading their implementations to make it work right."

However, as Robert notes, the implementors had already gone through all
the work of degrading their implementations, so the damage was done.

> Finally, it was fixed, in a rather nice and general way in Ada 95.

Yes, it falls out naturally as a consequence of more general rules about
"return by reference".

> Anyone want to add to or amend this bit of history (trying to remember
> things from this far back in detail is always a bit unreliable :-)

This time Robert's memory and mine are in accord.  :-)

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




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

* Re: Deallocating Task objects
  1997-02-20  0:00         ` Norman H. Cohen
@ 1997-02-21  0:00           ` Robert Dewar
  0 siblings, 0 replies; 8+ messages in thread
From: Robert Dewar @ 1997-02-21  0:00 UTC (permalink / raw)



<<It was not declared erroneous in Ada 83.  The ARG defined a new AI
category, "pathological", which said that the question at hand had
nothing to do with anything that could ever be useful in a real program,
and that even if the language gave a definite answer to the question, it
was not useful to write an ACVC test that would force implementors to
degrade their code to conform to that answer.  The later AI simply
reclassified the earlier AI from "binding interpretation" to
"pathological", meaning "Yes, a terminated task can be returned outside
of its master, but it's utterly useless to write a program that does
this, so we don't care if it works right, and we don't want implementors
degrading their implementations to make it work right.">>

said Norman. Right, that's my memory too, note that the really important
idea behind the pathological categorization was to stop the ACVC folks
from generating a test. It was really the ACVC test that damaged the
implementations in this case, not the original ARG ruling itself.

These days, with the new usage oriented viewpoint of the ACVC, such a test
would be unlikely to see the light of day even if the situation had not
been fixed in Ada 95 :-)





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

end of thread, other threads:[~1997-02-21  0:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-02-15  0:00 Deallocating Task objects Jonas Nygren
1997-02-15  0:00 ` Robert Dewar
1997-02-17  0:00 ` Mats Weber
1997-02-18  0:00   ` Robert L. Spooner
1997-02-18  0:00     ` Robert A Duff
1997-02-18  0:00       ` Robert Dewar
1997-02-20  0:00         ` Norman H. Cohen
1997-02-21  0:00           ` Robert Dewar

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