comp.lang.ada
 help / color / mirror / Atom feed
* DYNAMIC ADA TASK CREATION?
@ 2003-06-17 19:53 avram
  2003-06-17 20:24 ` Simon Wright
  0 siblings, 1 reply; 28+ messages in thread
From: avram @ 2003-06-17 19:53 UTC (permalink / raw)


  How to create dynamic for example N tasks. I don't know how create N of
tasks and array (not list). For example user interface gets an Integer (N)
from user and then we create N number of Task in ADA. How to do this?Can
anybody help me?
Thanx very much.





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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-17 19:53 DYNAMIC ADA TASK CREATION? avram
@ 2003-06-17 20:24 ` Simon Wright
  2003-06-18  6:11   ` Robert I. Eachus
  0 siblings, 1 reply; 28+ messages in thread
From: Simon Wright @ 2003-06-17 20:24 UTC (permalink / raw)


"avram" <avram79@tlen.pl> writes:

>   How to create dynamic for example N tasks. I don't know how create N of
> tasks and array (not list). For example user interface gets an Integer (N)
> from user and then we create N number of Task in ADA. How to do this?Can
> anybody help me?

(uncompiled)

  task type t is
    --  some entries
  end t;

  task body t is
  begin
    --  code
  end t;

  type ts is array (positive range <>) of t;

  n : positive;

begin

  --  read in n  

  declare
    the_ts : ts (1 .. n);
  begin
    --  do something with the tasks
    --  NB, can't pass this point until all the tasks have terminated
  end;

    



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-17 20:24 ` Simon Wright
@ 2003-06-18  6:11   ` Robert I. Eachus
  2003-06-18  9:20     ` Georg Bauhaus
  2003-06-18 19:15     ` avram
  0 siblings, 2 replies; 28+ messages in thread
From: Robert I. Eachus @ 2003-06-18  6:11 UTC (permalink / raw)


Simon Wright wrote:

>>  How to create dynamic for example N tasks. I don't know how create N of
>>tasks and array (not list). For example user interface gets an Integer (N)
>>from user and then we create N number of Task in ADA. How to do this?Can
>>anybody help me?
> 
> 
> (uncompiled)
> 
>   task type t is
>     --  some entries
>   end t;
> 
>   task body t is
>   begin
>     --  code
>   end t;
> 
>   type ts is array (positive range <>) of t;
> 
>   n : positive;
> 
> begin
> 
>   --  read in n  
> 
>   declare
>     the_ts : ts (1 .. n);
>   begin
>     --  do something with the tasks
>     --  NB, can't pass this point until all the tasks have terminated
>   end;

Correct.  But if you don't want to get stuck there, do this instead:

     -- task type t as above
     type ta is access t;

     type ts is array (positive range <>) of ta := new t;

     n : positive;

   begin

     --  read in n

     declare
       the_ts : ts (1 .. n);
     begin
       --  do something with the tasks
       --  NB, CAN pass this once all the tasks have been created.
     end;

For an ordinary task object, the creator of the object is the master (in 
the original example, a declare block.  But for a task created by an 
allocator, the place where the access type was declared determines who 
is the master.  (In either case, if that is in a library package, the 
master is the environment task.)




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18  6:11   ` Robert I. Eachus
@ 2003-06-18  9:20     ` Georg Bauhaus
  2003-06-18 11:13       ` John McCabe
  2003-06-18 19:15     ` avram
  1 sibling, 1 reply; 28+ messages in thread
From: Georg Bauhaus @ 2003-06-18  9:20 UTC (permalink / raw)


Robert I. Eachus <rieachus@attbi.com> wrote:
: Simon Wright wrote:
: 
:> (uncompiled)
:> 
:>   task type t is
:>     --  some entries
:>   end t;
:> 
:>   task body t is
:>   begin
:>     --  code
:>   end t;
:> 
:>   type ts is array (positive range <>) of t;
:> 
:>   n : positive;
:> 
:> begin
:> 
:>   --  read in n  
:> 
:>   declare
:>     the_ts : ts (1 .. n);
:>   begin
:>     --  do something with the tasks
:>     --  NB, can't pass this point until all the tasks have terminated
:>   end;
: 
: Correct.  But if you don't want to get stuck there, do this instead:
: 
:     -- task type t as above
:     type ta is access t;
: 
:     type ts is array (positive range <>) of ta := new t;
                                                 ^^^^^^^^  
I think I got the idea and made me program to see the tasks working
outside the declare block. A good hint!
But is new t on the line above some new default initialisation
construct, or meant to abbreviate something? (The compiler complains.)
: 
 [...]
: 
:     declare
:       the_ts : ts (1 .. n);
:     begin
:       --  do something with the tasks
:       --  NB, CAN pass this once all the tasks have been created.
:     end;
: 
: For an ordinary task object, the creator of the object is the master (in 
: the original example, a declare block.  But for a task created by an 
: allocator, the place where the access type was declared determines who 
: is the master.  (In either case, if that is in a library package, the 
: master is the environment task.)
: 

--  Georg



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18  9:20     ` Georg Bauhaus
@ 2003-06-18 11:13       ` John McCabe
  2003-06-18 12:43         ` John McCabe
  2003-06-19  5:07         ` Simon Wright
  0 siblings, 2 replies; 28+ messages in thread
From: John McCabe @ 2003-06-18 11:13 UTC (permalink / raw)


On Wed, 18 Jun 2003 09:20:01 +0000 (UTC), Georg Bauhaus
<sb463ba@d2-hrz.uni-duisburg.de> wrote:


>: Correct.  But if you don't want to get stuck there, do this instead:
>: 
>:     -- task type t as above
>:     type ta is access t;
>: 
>:     type ts is array (positive range <>) of ta := new t;
>                                                 ^^^^^^^^  
>I think I got the idea and made me program to see the tasks working
>outside the declare block. A good hint!
>But is new t on the line above some new default initialisation
>construct, or meant to abbreviate something? (The compiler complains.)
: 
:     declare
:       the_ts : ts (1 .. n);
:     begin
:       --  do something with the tasks
:       --  NB, CAN pass this once all the tasks have been created.
:     end;
: 

I'm not surprised, you're trying to initialise a type!! Simon did say
he hadn't compiled this though!

You need to remove the ' := new t' at the end, then actually create
the tasks something like:

-- task type t as above
type ta is access t;

type ts is array (positive range <>) of ta;

declare
   the_ts : ts (1 .. n);
begin
   for Index in 1 .. n loop
      the_ts(n) := new t;
   end loop;

   --  do something with the tasks
   --  NB, CAN pass this once all the tasks have been created.
end;

Just a vague thought....does..

declare
   the_ts : ts (1 .. n) = (others => new t);
begin
....

compile?


Best Regards
John McCabe

To reply by email replace 'nospam' with 'assen'



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18 11:13       ` John McCabe
@ 2003-06-18 12:43         ` John McCabe
  2003-06-18 14:17           ` Georg Bauhaus
  2003-06-19  5:07         ` Simon Wright
  1 sibling, 1 reply; 28+ messages in thread
From: John McCabe @ 2003-06-18 12:43 UTC (permalink / raw)


On Wed, 18 Jun 2003 11:13:37 +0000 (UTC), john@nospam.demon.co.uk
(John McCabe) wrote:


>Just a vague thought....does..
>
>declare
>   the_ts : ts (1 .. n) = (others => new t);

Certainly won't without a : in front of the = !


Best Regards
John McCabe

To reply by email replace 'nospam' with 'assen'



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18 12:43         ` John McCabe
@ 2003-06-18 14:17           ` Georg Bauhaus
  0 siblings, 0 replies; 28+ messages in thread
From: Georg Bauhaus @ 2003-06-18 14:17 UTC (permalink / raw)


John McCabe <john@nospam.demon.co.uk> wrote:
: On Wed, 18 Jun 2003 11:13:37 +0000 (UTC), john@nospam.demon.co.uk
: (John McCabe) wrote:
: 
: 
:>Just a vague thought....does..
:>
:>declare
:>   the_ts : ts (1 .. n) = (others => new t);
: 
: Certainly won't without a : in front of the = !

Yeah, this is what I had
   declare
      the_ts : ts := (1..n => new t);

and now that I see it again, there is an opportunity to
change it,
   declare
      the_ts : constant ts := (1..n => new t);


-- Georg



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18  6:11   ` Robert I. Eachus
  2003-06-18  9:20     ` Georg Bauhaus
@ 2003-06-18 19:15     ` avram
  2003-06-18 21:17       ` Craig Carey
  2003-06-18 23:28       ` Robert I. Eachus
  1 sibling, 2 replies; 28+ messages in thread
From: avram @ 2003-06-18 19:15 UTC (permalink / raw)


   Thanx very much.
  I have one more question.
What about task memory deallocation.
 How to wait untill task ends?
Is it possible to deallocate memory after the end of task from "parent task"
?
avram

Uzytkownik "Robert I. Eachus" <rieachus@attbi.com> napisal w wiadomosci
news:3EF0026E.2050309@attbi.com...
> Simon Wright wrote:
>
> >>  How to create dynamic for example N tasks. I don't know how create N
of
> >>tasks and array (not list). For example user interface gets an Integer
(N)
> >>from user and then we create N number of Task in ADA. How to do this?Can
> >>anybody help me?
> >
> >
> > (uncompiled)
> >
> >   task type t is
> >     --  some entries
> >   end t;
> >
> >   task body t is
> >   begin
> >     --  code
> >   end t;
> >
> >   type ts is array (positive range <>) of t;
> >
> >   n : positive;
> >
> > begin
> >
> >   --  read in n
> >
> >   declare
> >     the_ts : ts (1 .. n);
> >   begin
> >     --  do something with the tasks
> >     --  NB, can't pass this point until all the tasks have terminated
> >   end;
>
> Correct.  But if you don't want to get stuck there, do this instead:
>
>      -- task type t as above
>      type ta is access t;
>
>      type ts is array (positive range <>) of ta := new t;
>
>      n : positive;
>
>    begin
>
>      --  read in n
>
>      declare
>        the_ts : ts (1 .. n);
>      begin
>        --  do something with the tasks
>        --  NB, CAN pass this once all the tasks have been created.
>      end;
>
> For an ordinary task object, the creator of the object is the master (in
> the original example, a declare block.  But for a task created by an
> allocator, the place where the access type was declared determines who
> is the master.  (In either case, if that is in a library package, the
> master is the environment task.)
>





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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18 19:15     ` avram
@ 2003-06-18 21:17       ` Craig Carey
  2003-06-20 18:56         ` avram
  2003-06-18 23:28       ` Robert I. Eachus
  1 sibling, 1 reply; 28+ messages in thread
From: Craig Carey @ 2003-06-18 21:17 UTC (permalink / raw)


On Wed, 18 Jun 2003 21:15:02 +0200, "avram" <avram79@tlen.pl> wrote:
> Than[s] very much. I have one more question.
>What about task memory deallocation. How to wait untill task ends?

There was a solution posted in comp.lang.ada which is replicated:


On 11 May 2003 17:35:18 +0200, in comp.lang.ada you Pascal Obry wrote:
>[...] The delay could still not be enough. What I usually do
>is loop until 'Terminated is true.
...
>    for K in 1 .. 20_000 loop
>       X := new A.Tt;    --  [Create a new task]
>       N := N + 1;
>       X.The_End;
>
>       loop
>          exit when X'Terminated;
>          delay 1.0E-30;
>       end loop;
>
>       Free (X);
>    end loop;     
>

The memory recovery can be 0% efficient, or 100% efficient depending
on how the test is done (at least, for the ObjectAda and GNAT
compilers).

Craig Carey




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18 19:15     ` avram
  2003-06-18 21:17       ` Craig Carey
@ 2003-06-18 23:28       ` Robert I. Eachus
  2003-06-19  5:09         ` Simon Wright
  1 sibling, 1 reply; 28+ messages in thread
From: Robert I. Eachus @ 2003-06-18 23:28 UTC (permalink / raw)


avram wrote:
>    Thanx very much.
>   I have one more question.
> What about task memory deallocation.
>  How to wait untill task ends?
> Is it possible to deallocate memory after the end of task from "parent task"

If you really want to.  If the task is created with an allocator, you 
can test for TA(...)'Terminated and call an instance of 
Unchecked_Deallocation for the task access value.  (You can call 
Unchecked_Deallocation on an unterminated task, but it is not a good 
idea, in general.  It is a bad idea if the task has discriminants.)




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18 11:13       ` John McCabe
  2003-06-18 12:43         ` John McCabe
@ 2003-06-19  5:07         ` Simon Wright
  2003-06-19  6:05           ` Robert I. Eachus
  1 sibling, 1 reply; 28+ messages in thread
From: Simon Wright @ 2003-06-19  5:07 UTC (permalink / raw)


john@nospam.demon.co.uk (John McCabe) writes:

w> >: Correct.  But if you don't want to get stuck there, do this instead:
> >: 
> >:     -- task type t as above
> >:     type ta is access t;
> >: 
> >:     type ts is array (positive range <>) of ta := new t;
> >                                                 ^^^^^^^^  

[..]

> I'm not surprised, you're trying to initialise a type!! Simon did
> say he hadn't compiled this though!

That version was Robert's ...



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18 23:28       ` Robert I. Eachus
@ 2003-06-19  5:09         ` Simon Wright
  2003-06-19  6:39           ` Robert I. Eachus
  0 siblings, 1 reply; 28+ messages in thread
From: Simon Wright @ 2003-06-19  5:09 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> writes:

> If you really want to.  If the task is created with an allocator,
> you can test for TA(...)'Terminated and call an instance of
> Unchecked_Deallocation for the task access value.  (You can call
> Unchecked_Deallocation on an unterminated task, but it is not a good
> idea, in general.  It is a bad idea if the task has discriminants.)

Oh, why is it worse with discriminants?



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-19  5:07         ` Simon Wright
@ 2003-06-19  6:05           ` Robert I. Eachus
  2003-06-19 23:30             ` Jeffrey Carter
  0 siblings, 1 reply; 28+ messages in thread
From: Robert I. Eachus @ 2003-06-19  6:05 UTC (permalink / raw)


Simon Wright wrote:

>>>:     type ts is array (positive range <>) of ta := new t;
>>>                                                ^^^^^^^^  

> That version was Robert's ...

Let me make it official, it was a typo, should have been:

   type ts is array (positive range <>) of ta := (others => new t);

But I really wanted to answer this:

   Oh, why is it worse with discriminants?

There are usually in Ada implementations two types of storage associated 
with tasks.  The first is a task descriptor, which contains addresses 
for the code, entry queues, and other such stuff.  The other part is a 
stack and (and possibly local heap) for the executing object.  If the 
task has descriminants, they are normally stored in the task descriptor. 
Again in the normal case, the stack (and local heap if allocated) will 
be deallocated when the task terminates.  The task descriptor is the 
thing that can be deallocated by Unchecked_Deallocation.

If a task without discriminants is freed before it becomes terminated, 
it won't affect the executing task.  But it may deallocate the task 
descriptor which contains the discriminants.  If the task, or any of 
it's dependent tasks references the discriminants, it is a bounded 
error, which will most likely cause Program_Error in the task.  See RM 
13.11.2(11-15) for details on other possibilities.

For a task without discriminants, you may not free all the memory that 
you had hoped for, but the only real effect is that you may no longer be 
able to reference the task.  (Of course, calling an instance of 
Unchecked_Deallocation while salting away a copy of the pointer is not 
something you should do either.  But that case is a lot more obvious.)

In most normal tasking programs there is no particular reason to free 
the task descriptors.  And as I said, the memory allocated for the stack 
will go away anyway when the task is terminated.  (In language lawyer 
speak, a task is completed when the code execution reaches the end of 
the code and in other cases.  But termination waits until all dependent 
tasks have become terminated.  This is so that dependent tasks can still 
reference the parent task's stack.)

So usually when a programmer thinks he wants to go around stomping out 
tasks, he has left one or two tasks hanging that are keeping a lot of 
other tasks half-alive.




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-19  5:09         ` Simon Wright
@ 2003-06-19  6:39           ` Robert I. Eachus
  2003-06-19 20:34             ` Simon Wright
  2003-06-28  0:54             ` Matthew Heaney
  0 siblings, 2 replies; 28+ messages in thread
From: Robert I. Eachus @ 2003-06-19  6:39 UTC (permalink / raw)


I said:
>>If you really want to.  If the task is created with an allocator,
>>you can test for TA(...)'Terminated and call an instance of
>>Unchecked_Deallocation for the task access value.  (You can call
>>Unchecked_Deallocation on an unterminated task, but it is not a good
>>idea, in general.  It is a bad idea if the task has discriminants.)

After I answered Simon's question, I realized that the information in 
the Ada Reference Manual can really be divided into three parts:

1) (The smallest.) What you need to know to develop good software
    in Ada.

2) How to shoot yourself in the foot, if you really want to.

3) Where the bullet may go if you choose something from the second
    section.

But what is totally missing from the RM is why shooting yourself in the 
foot is a bad idea.  In this case, all the ordinary programmer should 
need to know is:

A. Deallocating an unterminated task is certain not to be useful.
B. Deallocating a terminated task is probably just as useless, but
    harmless.

So why does the Ada RM spend so many words on this case?  Othogonality. 
  There are times when a programmer will create an object type that 
contains tasks.  And he may want to use, say, a container package for 
objects of this type. (Yes, most container libraries refuse to work with 
limited data objects, but not all.)  So the Reference Manual has to 
carefully define what happens when you deallocate a task object so that 
everything works together the way it should in that case.

It is just like that discussion of garbage collectors for Ada.  Are they 
allowed? Sure.  Does the Reference Manual go to great lengths to allow 
Ada implementations for environments that have garbarge collectors? 
Sure, in fact there have been several Ada compilers that did target 
machines with garbage collection.  The most popular was probably the Ada 
83 Symbolics compiler.

But should any user care if the target environment supports garbage 
collection?  Of course not.  Creating garbage in Ada means you are in 
section 2 or section 3, not section 1.  There are debuggers, tools and 
special compiler options to allow you to find where garbage is being 
created in an Ada program.  But they are useful precisely because ANY 
garbage in an Ada program is evidence of a bug.

This used to not be true.  In fact Dave Emery and I got criticized for 
distributing a package for reading and using command line parameters 
that left garbage behind.  Of course, it was a copy of the command line 
parameters, and no matter how many times you used the facilities in the 
package, there was still at most one copy of the command line that could 
be considered garbage.

How did we fix it?  Got Ada.Command_Line, and Ada.Strings.Unbounded 
added in Ada95.  How's that for a belt and suspenders fix. ;-)




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-19  6:39           ` Robert I. Eachus
@ 2003-06-19 20:34             ` Simon Wright
  2003-06-28  0:54             ` Matthew Heaney
  1 sibling, 0 replies; 28+ messages in thread
From: Simon Wright @ 2003-06-19 20:34 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> writes:

(enlightening replies on deleting allocated tasks, snipped)

Thanks!



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-19  6:05           ` Robert I. Eachus
@ 2003-06-19 23:30             ` Jeffrey Carter
  0 siblings, 0 replies; 28+ messages in thread
From: Jeffrey Carter @ 2003-06-19 23:30 UTC (permalink / raw)


Robert I. Eachus wrote:
> Simon Wright wrote:
> 
>   type ts is array (positive range <>) of ta := (others => new t);

I'd still like to know what language this is.

-- 
Jeff Carter
"You cheesy lot of second-hand electric donkey-bottom biters."
Monty Python & the Holy Grail




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-18 21:17       ` Craig Carey
@ 2003-06-20 18:56         ` avram
  2003-06-21 13:06           ` Pascal Obry
  0 siblings, 1 reply; 28+ messages in thread
From: avram @ 2003-06-20 18:56 UTC (permalink / raw)


   Thanx, but i think that the loop is not efficient. I mean this is an
active waiting, so my main process use CPU without sense. I would like to
know if there is way to deallocation of a memory without active waiting.

avram

Uzytkownik "Craig Carey" <research@ijs.co.nz> napisal w wiadomosci
news:39l1fv8ig2hr2bpsf786ao6a9it649bfnj@4ax.com...
> On Wed, 18 Jun 2003 21:15:02 +0200, "avram" <avram79@tlen.pl> wrote:
> > Than[s] very much. I have one more question.
> >What about task memory deallocation. How to wait untill task ends?
>
> There was a solution posted in comp.lang.ada which is replicated:
>
>
> On 11 May 2003 17:35:18 +0200, in comp.lang.ada you Pascal Obry wrote:
> >[...] The delay could still not be enough. What I usually do
> >is loop until 'Terminated is true.
> ...
> >    for K in 1 .. 20_000 loop
> >       X := new A.Tt;    --  [Create a new task]
> >       N := N + 1;
> >       X.The_End;
> >
> >       loop
> >          exit when X'Terminated;
> >          delay 1.0E-30;
> >       end loop;
> >
> >       Free (X);
> >    end loop;
> >
>
> The memory recovery can be 0% efficient, or 100% efficient depending
> on how the test is done (at least, for the ObjectAda and GNAT
> compilers).
>
> Craig Carey
>





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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-20 18:56         ` avram
@ 2003-06-21 13:06           ` Pascal Obry
  0 siblings, 0 replies; 28+ messages in thread
From: Pascal Obry @ 2003-06-21 13:06 UTC (permalink / raw)



"avram" <avram79@tlen.pl> writes:

>    Thanx, but i think that the loop is not efficient. I mean this is an
> active waiting, so my main process use CPU without sense. I would like to
> know if there is way to deallocation of a memory without active waiting.

No. The whole point of the loop is to waity for the task to terminate before
freeing memory. How do you expect to be able to free memory of an active
task ?

Note that this loop will iterate once or twice in most of the case. Not a big
deal.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|         http://perso.wanadoo.fr/pascal.obry
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-19  6:39           ` Robert I. Eachus
  2003-06-19 20:34             ` Simon Wright
@ 2003-06-28  0:54             ` Matthew Heaney
  2003-06-28  7:25               ` Robert I. Eachus
  1 sibling, 1 reply; 28+ messages in thread
From: Matthew Heaney @ 2003-06-28  0:54 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> wrote in message news:<3EF15A7C.4030901@attbi.com>...

>   There are times when a programmer will create an object type that 
> contains tasks.  And he may want to use, say, a container package for 
> objects of this type. (Yes, most container libraries refuse to work with 
> limited data objects, but not all.)

The new release of the Charles library does indeed work with element
types that are limited.  The basic idea is that when you insert an
element into the container, the element is allocated with its default
value -- whatever that means for the element type.  For example, for
an element type that is controlled, controlled initialization will
occur.

The list works like this:

procedure Op (List : in out List_Subtype) is
begin
   Push_Back (List);

   declare
      I : constant Iterator_Type := Last (List);
      E : Limited_Element_Type renames To_Access (I).all;
   begin
      --now manipulate E as desired
   end;
end Op;

A map works like this:

procedure Op (Map : in out Map_Subtype) is
   I : Iterator_Type;
begin
   Insert (Map, Key, I);

   declare
      E : Limited_Element_Type renames To_Access (I).all;
   begin
      --now manipulate E as desired
   end;
end Op;

For example, this schema allows you to create a map of File_Type,
indexed by its file name (of type String).  For example:

procedure Insert
  (Map  : in out Map_Subtype;
   Name : in     String) is

   I : Iterator_Type;
begin
   Insert (Map, Key => Name, Iterator => I);

   declare
      File : File_Type renames To_Access (I).all;
   begin
      Open (File, Mode => Out_File, Name => Name);
      --...
   end;
end Insert;


Not all of the containers for limited elements are there yet -- I
still have to do the multisets and multimaps.  I'll post them next
week (30 June 2003).

http://home.earthlink.net/~matthewjheaney/charles/index.html

http://home.earthlink.net/~matthewjheaney/charles/charles-20030627.zip

I also posted the slides from my paper presentation about Charles at
the Ada-Europe 2003 conference which took place last week in Toulouse,
France.

http://home.earthlink.net/~matthewjheaney/charles/charles.ppt

http://home.earthlink.net/~matthewjheaney/charles/charlesppt.pdf

http://home.earthlink.net/~matthewjheaney/charles/charlesppt.htm



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-28  0:54             ` Matthew Heaney
@ 2003-06-28  7:25               ` Robert I. Eachus
  2003-06-30  7:35                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 28+ messages in thread
From: Robert I. Eachus @ 2003-06-28  7:25 UTC (permalink / raw)



I wrote:
>>  There are times when a programmer will create an object type that 
>>contains tasks.  And he may want to use, say, a container package for 
>>objects of this type. (Yes, most container libraries refuse to work with 
>>limited data objects, but not all.)

Matthew Heaney wrote:
> The new release of the Charles library does indeed work with element
> types that are limited.  The basic idea is that when you insert an
> element into the container, the element is allocated with its default
> value -- whatever that means for the element type.  For example, for
> an element type that is controlled, controlled initialization will
> occur.

Not quite what I had in mind, but great.  I was thinking of container 
packages that manage references/access values, assuming that the 
original objects cannot be moved or changed.  When I need a package like 
this, I usually encapsulate a "normal" container library around a 
limited type and an explicit access type:

    generic
      type Element is limited private;
      type Pointer is access Element;
    package Limited_Stack is
      procedure Push(E: in Element);
      procedure Push(P: in Pointer);
      function Peek return Pointer;
      function Pop return Pointer;
      function Pop return Element; -- constant view...
    end Limited_Stack;

The explicit access type is because of the rules on return by reference 
providing a constant view.  I may propose as an Ada 0Y revision allowing 
return by reference functions where a view conversion would be allowed. 
  In other words, you could have a return by reference function as an in 
out parameter in another call.  It seems that should be part of AI-318, 
but AI-318 goes a lot further without addressing this at all. An 
alternative would be allowing a function to return an anonymous access type.




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-28  7:25               ` Robert I. Eachus
@ 2003-06-30  7:35                 ` Dmitry A. Kazakov
  2003-06-30 15:01                   ` Matthew Heaney
  2003-07-03  9:53                   ` Robert I. Eachus
  0 siblings, 2 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2003-06-30  7:35 UTC (permalink / raw)


On Sat, 28 Jun 2003 07:25:02 GMT, "Robert I. Eachus"
<rieachus@attbi.com> wrote:

>I wrote:
>>>  There are times when a programmer will create an object type that 
>>>contains tasks.  And he may want to use, say, a container package for 
>>>objects of this type. (Yes, most container libraries refuse to work with 
>>>limited data objects, but not all.)
>
>Matthew Heaney wrote:
>> The new release of the Charles library does indeed work with element
>> types that are limited.  The basic idea is that when you insert an
>> element into the container, the element is allocated with its default
>> value -- whatever that means for the element type.  For example, for
>> an element type that is controlled, controlled initialization will
>> occur.
>
>Not quite what I had in mind, but great.  I was thinking of container 
>packages that manage references/access values, assuming that the 
>original objects cannot be moved or changed.  When I need a package like 
>this, I usually encapsulate a "normal" container library around a 
>limited type and an explicit access type:
>
>    generic
>      type Element is limited private;

A short question. Why not:

   type Element (<>) is limited private;

[I am using this in my containers because it is weaker than just
limited private.]

>      type Pointer is access Element;
>    package Limited_Stack is
>      procedure Push(E: in Element);
>      procedure Push(P: in Pointer);
>      function Peek return Pointer;
>      function Pop return Pointer;
>      function Pop return Element; -- constant view...
>    end Limited_Stack;
>
>The explicit access type is because of the rules on return by reference 
>providing a constant view.  I may propose as an Ada 0Y revision allowing 
>return by reference functions where a view conversion would be allowed. 
>  In other words, you could have a return by reference function as an in 
>out parameter in another call.  It seems that should be part of AI-318, 
>but AI-318 goes a lot further without addressing this at all. An 
>alternative would be allowing a function to return an anonymous access type.

Or both! Returned anonymous access type could be very useful for
tagged types, because it would make operations returning a pointer
primitive and covariant, which is presently impossible.

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-30  7:35                 ` Dmitry A. Kazakov
@ 2003-06-30 15:01                   ` Matthew Heaney
  2003-07-01  7:19                     ` Dmitry A. Kazakov
  2003-07-02 12:05                     ` Mário Amado Alves
  2003-07-03  9:53                   ` Robert I. Eachus
  1 sibling, 2 replies; 28+ messages in thread
From: Matthew Heaney @ 2003-06-30 15:01 UTC (permalink / raw)


Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote in message news:<0gpvfv49qaa0b62ab5m0kg39kka66sis8t@4ax.com>...
> On Sat, 28 Jun 2003 07:25:02 GMT, "Robert I. Eachus"
> <rieachus@attbi.com> wrote:
> 
> >    generic
> >      type Element is limited private;
> 
> A short question. Why not:
> 
>    type Element (<>) is limited private;
> 
> [I am using this in my containers because it is weaker than just
> limited private.]

Because the type must be definite, of course!  Otherwise, how would
you know how much space to allocate for the object?

Consider the following type (as you've declared it above):

package P is
   type T (<>) is limited private;
private
   type T is limited null record;
end P;

Here's a little puzzle: how do you declare an instance of type T?



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-30 15:01                   ` Matthew Heaney
@ 2003-07-01  7:19                     ` Dmitry A. Kazakov
  2003-07-01 14:21                       ` Matthew Heaney
  2003-07-02 12:05                     ` Mário Amado Alves
  1 sibling, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2003-07-01  7:19 UTC (permalink / raw)


On 30 Jun 2003 08:01:29 -0700, mheaney@on2.com (Matthew Heaney) wrote:

>Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote in message news:<0gpvfv49qaa0b62ab5m0kg39kka66sis8t@4ax.com>...
>> On Sat, 28 Jun 2003 07:25:02 GMT, "Robert I. Eachus"
>> <rieachus@attbi.com> wrote:
>> 
>> >    generic
>> >      type Element is limited private;
>> 
>> A short question. Why not:
>> 
>>    type Element (<>) is limited private;
>> 
>> [I am using this in my containers because it is weaker than just
>> limited private.]
>
>Because the type must be definite, of course!  Otherwise, how would
>you know how much space to allocate for the object?
>
>Consider the following type (as you've declared it above):
>
>package P is
>   type T (<>) is limited private;
>private
>   type T is limited null record;
>end P;
>
>Here's a little puzzle: how do you declare an instance of type T?

I thought the container has only pointers to instances which are
created by caller, but maybe I missed something.

[ An advantage in having (<>) for Element is that it could then have
T'Class as actual. For example:

type Operand is new Ada.Finalization.Limited_Controlled with private;
type Operand_Ptr is access all Operand'Class;
...
package Argument_Stack is new Limited_Stack
   (Element => Operand'Class, Pointer => Operand_Ptr);
]

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-07-01  7:19                     ` Dmitry A. Kazakov
@ 2003-07-01 14:21                       ` Matthew Heaney
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew Heaney @ 2003-07-01 14:21 UTC (permalink / raw)


Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote in message news:<tnc2gvkr3fu9rpkd0tu56095ttbuflkgi9@4ax.com>...
> 
> I thought the container has only pointers to instances which are
> created by caller, but maybe I missed something.
> 
> [ An advantage in having (<>) for Element is that it could then have
> T'Class as actual. For example:
> 
> type Operand is new Ada.Finalization.Limited_Controlled with private;
> type Operand_Ptr is access all Operand'Class;
> ...
> package Argument_Stack is new Limited_Stack
>    (Element => Operand'Class, Pointer => Operand_Ptr);
> ]

Then we are comparing apples and oranges.  The containers I was
talking about are declared like this:

generic
   type Element_Type is limited private;
package Generic_Container is ...;

Strictly speaking your container doesn't have elements -- it has
pointers to elements.

The model in Charles is that an element is a component of an internal
node of storage, which is designated by an iterator.  If you want an
access object that designates the element, then you can use
Generic_Element to convert ("dereference") the iterator to the access
type.

Your container seems to have two levels of indirection: a pointer to
an internal node contains a pointer to the element.  In Charles there
is only a single level of indirection.

http://home.earthlink.net/~matthewjheaney/charles/index.html

Of course, there is still the problem of a container of elements of
indefinite type T'Class, which your container more or less solves.

There are at least a couple of ways to do that in Charles.  One way is
to use a nonlimited container of pointers:

package T_Class_Lists is 
  new Charles.Lists.Double.Unbounded (T_Class_Access);

Insert (List, New_Item => new T'Class'(...), Before => I);

This implies that you have to manually deallocate the items prior to
destruction of the container object, which you can do easily enough by
passing an instantiation of Unchecked_Deallocation as the generic
actual to Generic_Modify_Element.

If you want to automate the finalization of container elements then
you can use an Access_Control object as the element of a limited list:

package T_Class_Lists is
   new Charles.Lists.Double.Limited_Unbounded (Pointer_Type);

where Pointer_Type is an instantiation of Charles.Access_Control. 
(That package is analogous to the auto_ptr in C++.)

You'd do something like:

Insert (List, Before => I, Iterator => J);

declare
   P : Pointer_Type renames To_Access (J).all;
begin
   Initialize (P, new T'Class'(...));
end;

So now when you delete the item:

Delete (List, Iterator => J);

then Free will be invoked automatically as a side-effect of
finalization of the Pointer_Type object.

One of the things that is lacking in the C++ STL is that you can't use
an auto_ptr as a container element.  The limited containers in Charles
were partly motivated by a desire to provide that ability.  The syntax
is admittedly heavy, but you can ease the pain as desired by creating
a thin layer (either over just the insertion operations as in the
example above, or over the entire container).

If there is interest then perhaps we can generalize your original idea
by creating another container form:

generic
  type Element_Type (<>) is limited private;
  type Handle_Type is private;
  with procedure Finalize (Handle : in out Handle_Type) is <>;
package Generic_Indefinite_Containers is

  type Container_Type is limited private;

  procedure Insert 
    (Container : in out Container_Type;
     New_Item  : in     Handle_Type);

  ...
end Generic_Indefinite_Containers;

Of course we could be more specific, by using an access type directly
as the handle:

generic
  type Element_Type (<>) is limited private;
  type Element_Access is access all Element_Type;
  with procedure Free (X : in out Element_Access) is <>;
package Generic_Indefinite_Containers is ...;

It would be trivial to implement either of these as a thin layer over
the existing components in Charles, which is largely why I haven't
bothered creating a separate component for indefinite types.



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-30 15:01                   ` Matthew Heaney
  2003-07-01  7:19                     ` Dmitry A. Kazakov
@ 2003-07-02 12:05                     ` Mário Amado Alves
  2003-07-02 19:41                       ` Simon Wright
  1 sibling, 1 reply; 28+ messages in thread
From: Mário Amado Alves @ 2003-07-02 12:05 UTC (permalink / raw)


"Why not:
   type Element (<>) is limited private;" (Dmitri)

"Because the type must be definite, of course! Otherwise, how would
you know how much space to allocate for the object?" (Matthew)

With the amazing 'Size attribute, of course!

What I have *not* figured out yet is how to use the really amazing
'Definite attribute to choose the most efficient implementation
automatically (at compile or at run time).

Matthew should remember the small talk we had about this in Toulouse.
His impression was this is not possible and after a little research
that is my impression too. But never loose hope! Namely there is
always Ada 2015:

  -- Don't try this at home!
  generic
    type Element_Type (<>) is private;
  package Unbounded_Arrays is
    when Element'Definite =>
      new package Unbounded_Arrays_For_Definite_Elements
(Element_Type);
    when not =>
      new package Unbounded_Arrays_For_Nondefinite_Elements
(Element_Type);
  end;

Cheers,
--Marius



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-07-02 12:05                     ` Mário Amado Alves
@ 2003-07-02 19:41                       ` Simon Wright
  2003-07-03 21:31                         ` Mário Amado Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Simon Wright @ 2003-07-02 19:41 UTC (permalink / raw)


maa@liacc.up.pt (M�rio Amado Alves) writes:

> "Why not:
>    type Element (<>) is limited private;" (Dmitri)
> 
> "Because the type must be definite, of course! Otherwise, how would
> you know how much space to allocate for the object?" (Matthew)
> 
> With the amazing 'Size attribute, of course!

Am I missing something? I thought the point of indefinite types was
that different objects of the type might have different sizes?



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

* Re: DYNAMIC ADA TASK CREATION?
  2003-06-30  7:35                 ` Dmitry A. Kazakov
  2003-06-30 15:01                   ` Matthew Heaney
@ 2003-07-03  9:53                   ` Robert I. Eachus
  1 sibling, 0 replies; 28+ messages in thread
From: Robert I. Eachus @ 2003-07-03  9:53 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> A short question. Why not:
> 
>    type Element (<>) is limited private;
> 
> [I am using this in my containers because it is weaker than just
> limited private.]

A short answer, Matt has provided additional discussion.  There are many 
cases in Ada where you can wrap a limited object with discriminants in a 
record without discriminats.  It seems crazy, but the package which is 
now Ada.Strings.Bounded started out as a "trick" I kept distributing to 
show how to do it.

-- 

                                                        Robert I. Eachus

�In an ally, considerations of house, clan, planet, race are 
insignificant beside two prime questions, which are: 1. Can he shoot? 2. 
Will he aim at your enemy?� -- from the Laiden novels by Sharon Lee and 
Steve Miller.




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

* Re: DYNAMIC ADA TASK CREATION?
  2003-07-02 19:41                       ` Simon Wright
@ 2003-07-03 21:31                         ` Mário Amado Alves
  0 siblings, 0 replies; 28+ messages in thread
From: Mário Amado Alves @ 2003-07-03 21:31 UTC (permalink / raw)


> > "Why not:
> >    type Element (<>) is limited private;" (Dmitri)
> > 
> > "Because the type must be definite, of course! Otherwise, how would
> > you know how much space to allocate for the object?" (Matthew)
> > 
> > With the amazing 'Size attribute, of course! (Marius)
> 
> Am I missing something? I thought the point of indefinite types was
> that different objects of the type might have different sizes? (Simon)

It is. I was refering to Object'Size, not Type'Size, of course.
Type'Size for indefinite types is of course nonsense (ARM says
implementation defined). Object'Size tells you exactly "how much space
to allocate for the object". (Unless Matt's "object" is the container,
not the element. But is there any interesting container with an priori
known size, even for definite elements?)



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

end of thread, other threads:[~2003-07-03 21:31 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-17 19:53 DYNAMIC ADA TASK CREATION? avram
2003-06-17 20:24 ` Simon Wright
2003-06-18  6:11   ` Robert I. Eachus
2003-06-18  9:20     ` Georg Bauhaus
2003-06-18 11:13       ` John McCabe
2003-06-18 12:43         ` John McCabe
2003-06-18 14:17           ` Georg Bauhaus
2003-06-19  5:07         ` Simon Wright
2003-06-19  6:05           ` Robert I. Eachus
2003-06-19 23:30             ` Jeffrey Carter
2003-06-18 19:15     ` avram
2003-06-18 21:17       ` Craig Carey
2003-06-20 18:56         ` avram
2003-06-21 13:06           ` Pascal Obry
2003-06-18 23:28       ` Robert I. Eachus
2003-06-19  5:09         ` Simon Wright
2003-06-19  6:39           ` Robert I. Eachus
2003-06-19 20:34             ` Simon Wright
2003-06-28  0:54             ` Matthew Heaney
2003-06-28  7:25               ` Robert I. Eachus
2003-06-30  7:35                 ` Dmitry A. Kazakov
2003-06-30 15:01                   ` Matthew Heaney
2003-07-01  7:19                     ` Dmitry A. Kazakov
2003-07-01 14:21                       ` Matthew Heaney
2003-07-02 12:05                     ` Mário Amado Alves
2003-07-02 19:41                       ` Simon Wright
2003-07-03 21:31                         ` Mário Amado Alves
2003-07-03  9:53                   ` Robert I. Eachus

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