comp.lang.ada
 help / color / mirror / Atom feed
* Initializing an array of tasks with discrimants
@ 2019-11-22 22:07 Jere
  2019-11-22 22:39 ` Jeffrey R. Carter
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Jere @ 2019-11-22 22:07 UTC (permalink / raw)


I recently ran into a situation where I had an array
of tasks that had discriminants (with a default), but 
I couldn't find a simple way to initialize them.  I 
did come up with a workaround, but wanted to see if
the language defined a way to do this:

    task type T(D: Integer := 3);
    
    task body T is 
    begin 
        null; 
    end T;
    
    type A is array (Integer range <>) of T;
    
    V : A(1..10) := ?????????

If they all had the same discriminant value, I
can just create a subtype and do an array of 
the subtype, but in this case, the discriminants
would not all be the same.

My work around was a wrapper type:

    type Wrapper(D : Integer := 0) is record
        Impl : T(D);
    end record.

    type A is array (Integer range <>) of Wrapper;

    V : A(1..10) := (1 => (D => 1, others => <>), and so on

But I was hoping there was a better way to do it simply.
The Wrapper record isn't there to represent the 
intended design and doesn't really improve readability.
It's essentially a workaround for something I cannot 
figure out.

I tried many variations of qualified expressions and 
aggregates on the original task type elements, but all
of them gave me errors about it expected the task type
but found a composite type instead.

Is there a particular aggregate that I can use to avoid
the superfluous wrapper record?


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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 22:07 Initializing an array of tasks with discrimants Jere
@ 2019-11-22 22:39 ` Jeffrey R. Carter
  2019-11-23 16:23   ` Jere
  2019-11-22 23:57 ` Robert A Duff
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Jeffrey R. Carter @ 2019-11-22 22:39 UTC (permalink / raw)


On 11/22/19 11:07 PM, Jere wrote:
> I recently ran into a situation where I had an array
> of tasks that had discriminants (with a default), but
> I couldn't find a simple way to initialize them.  I
> did come up with a workaround, but wanted to see if
> the language defined a way to do this:

The standard way to do this is for the default to be a function call:

Next_Value : Positive := 1;

function Next return Positive is
    Result : constant Positive := Next_Value;
begin -- Next
    Next_Value := Next_Value + 1;

    return Result;
end Next;

task type T (D : Positive := Next);

type T_List is array (Positive range <>) of T;

A : T_List (1 .. Num_Tasks);

The language guarantees that the calls to Next will occur sequentially. The 
order of the calls is not defined, so there is no guarantee that the index and 
discriminant of a T in A will be the same.

-- 
Jeff Carter
"I would never want to belong to any club that
would have someone like me for a member."
Annie Hall
41


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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 22:07 Initializing an array of tasks with discrimants Jere
  2019-11-22 22:39 ` Jeffrey R. Carter
@ 2019-11-22 23:57 ` Robert A Duff
  2019-11-23  0:27   ` Anh Vo
                     ` (2 more replies)
  2019-11-23  8:29 ` Dmitry A. Kazakov
  2019-11-23 16:57 ` Jere
  3 siblings, 3 replies; 13+ messages in thread
From: Robert A Duff @ 2019-11-22 23:57 UTC (permalink / raw)


Jere <jhb.chat@gmail.com> writes:

> Is there a particular aggregate that I can use to avoid
> the superfluous wrapper record?

See AI12-0212-1.TXT.  Not yet implemented in GNAT,
as far as I know.

- Bob


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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 23:57 ` Robert A Duff
@ 2019-11-23  0:27   ` Anh Vo
  2019-11-23  9:12   ` Randy Brukardt
  2019-11-23 16:25   ` Jere
  2 siblings, 0 replies; 13+ messages in thread
From: Anh Vo @ 2019-11-23  0:27 UTC (permalink / raw)


On Friday, November 22, 2019 at 3:57:52 PM UTC-8, Robert A Duff wrote:
> Jere <jhb.chat@gmail.com> writes:
> 
> > Is there a particular aggregate that I can use to avoid
> > the superfluous wrapper record?
> 
> See AI12-0212-1.TXT.  Not yet implemented in GNAT,
> as far as I know.

I would add precondition to Next as

function Next return Positive with pre => Next_Value < Positive'Last;

Anh Vo


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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 22:07 Initializing an array of tasks with discrimants Jere
  2019-11-22 22:39 ` Jeffrey R. Carter
  2019-11-22 23:57 ` Robert A Duff
@ 2019-11-23  8:29 ` Dmitry A. Kazakov
  2019-11-23 16:28   ` Jere
  2019-11-23 16:57 ` Jere
  3 siblings, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2019-11-23  8:29 UTC (permalink / raw)


On 2019-11-22 23:07, Jere wrote:
> I recently ran into a situation where I had an array
> of tasks that had discriminants (with a default), but
> I couldn't find a simple way to initialize them.  I
> did come up with a workaround, but wanted to see if
> the language defined a way to do this:
> 
>      task type T(D: Integer := 3);

The cleanest way would be a protected generator of unique task IDs:

    protected ID is
       procedure Get (ID : out Integer);
    private
       Free : Integer := 0;
    end ID;

       procedure Get (ID : out Integer) is
       begin
           ID := Free;
           Free := Free + 1;
       end Get;

    task body T is
       D : Integer;
    begin
       ID.Get (D);
       ...
    end T;

No discriminants.

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


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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 23:57 ` Robert A Duff
  2019-11-23  0:27   ` Anh Vo
@ 2019-11-23  9:12   ` Randy Brukardt
  2019-11-23 16:50     ` Jere
  2019-11-23 16:25   ` Jere
  2 siblings, 1 reply; 13+ messages in thread
From: Randy Brukardt @ 2019-11-23  9:12 UTC (permalink / raw)


"Robert A Duff" <bobduff@TheWorld.com> wrote in message 
news:wcca78nzcox.fsf@shell02.theworld.com...
> Jere <jhb.chat@gmail.com> writes:
>
>> Is there a particular aggregate that I can use to avoid
>> the superfluous wrapper record?
>
> See AI12-0212-1.TXT.  Not yet implemented in GNAT,
> as far as I know.

If you wanted the indexes in order, you could use AI12-0061-1 (but I don't 
know if that is implemented in GNAT yet, either):

     (for I in 1 .. 10 => (D => I, others => <>))

That still needs the wrapper record as I don't think you can write an 
aggregate for a task. But a lot shorter.

                                        Randy.



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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 22:39 ` Jeffrey R. Carter
@ 2019-11-23 16:23   ` Jere
  0 siblings, 0 replies; 13+ messages in thread
From: Jere @ 2019-11-23 16:23 UTC (permalink / raw)


On Friday, November 22, 2019 at 5:39:57 PM UTC-5, Jeffrey R. Carter wrote:
> On 11/22/19 11:07 PM, Jere wrote:
> > I recently ran into a situation where I had an array
> > of tasks that had discriminants (with a default), but
> > I couldn't find a simple way to initialize them.  I
> > did come up with a workaround, but wanted to see if
> > the language defined a way to do this:
> 
> The standard way to do this is for the default to be a function call:
> 
> Next_Value : Positive := 1;
> 
> function Next return Positive is
>     Result : constant Positive := Next_Value;
> begin -- Next
>     Next_Value := Next_Value + 1;
> 
>     return Result;
> end Next;
> 
> task type T (D : Positive := Next);
> 
> type T_List is array (Positive range <>) of T;
> 
> A : T_List (1 .. Num_Tasks);
> 
> The language guarantees that the calls to Next will occur sequentially. The 
> order of the calls is not defined, so there is no guarantee that the index and 
> discriminant of a T in A will be the same.
> 

Thanks!  That said, my issue isn't so much generating the numbers
(They would not have any particular pattern anyways), but trying
to figure out if there is an aggregate or qualified expression for
initializing tasks with discriminants that I could use.  I was hoping
that simply T'(D => 2) would have worked, but the compiler complains
about being a composite.  On one level I understand why, but on another
given how strongly typed Ada is, I was hoping the language provided
some type of initialization aggregate.

This is still a good solution for when the discriminants will have  a
known pattern by design though.  I will file it away for that
situation, so thank you.

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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 23:57 ` Robert A Duff
  2019-11-23  0:27   ` Anh Vo
  2019-11-23  9:12   ` Randy Brukardt
@ 2019-11-23 16:25   ` Jere
  2 siblings, 0 replies; 13+ messages in thread
From: Jere @ 2019-11-23 16:25 UTC (permalink / raw)


On Friday, November 22, 2019 at 6:57:52 PM UTC-5, Robert A Duff wrote:
> Jere writes:
> 
> > Is there a particular aggregate that I can use to avoid
> > the superfluous wrapper record?
> 
> See AI12-0212-1.TXT.  Not yet implemented in GNAT,
> as far as I know.
> 
> - Bob

So I googled that, but on the page that the search provided didn't
seem to have anything that I could see to initializing task types
with discriminants.  It showed a lot on how to initialize containers,
but I didn't see anything for tasks.  What am I missing there?

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

* Re: Initializing an array of tasks with discrimants
  2019-11-23  8:29 ` Dmitry A. Kazakov
@ 2019-11-23 16:28   ` Jere
  2019-11-23 17:03     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 13+ messages in thread
From: Jere @ 2019-11-23 16:28 UTC (permalink / raw)


On Saturday, November 23, 2019 at 3:29:45 AM UTC-5, Dmitry A. Kazakov wrote:
> On 2019-11-22 23:07, Jere wrote:
> > I recently ran into a situation where I had an array
> > of tasks that had discriminants (with a default), but
> > I couldn't find a simple way to initialize them.  I
> > did come up with a workaround, but wanted to see if
> > the language defined a way to do this:
> > 
> >      task type T(D: Integer := 3);
> 
> The cleanest way would be a protected generator of unique task IDs:
> 
>     protected ID is
>        procedure Get (ID : out Integer);
>     private
>        Free : Integer := 0;
>     end ID;
> 
>        procedure Get (ID : out Integer) is
>        begin
>            ID := Free;
>            Free := Free + 1;
>        end Get;
> 
>     task body T is
>        D : Integer;
>     begin
>        ID.Get (D);
>        ...
>     end T;
> 
> No discriminants.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Yes, for ID's.  I really dialed down the example
code for simplicity.  The actual scenario isn't 
ID's but a set of enumerations that provide
configuration data for the tasks.  They wouldn't
be unique or in any order.  I was mostly just seeing
if I could do away with the wrapper record for 
initialization.


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

* Re: Initializing an array of tasks with discrimants
  2019-11-23  9:12   ` Randy Brukardt
@ 2019-11-23 16:50     ` Jere
  0 siblings, 0 replies; 13+ messages in thread
From: Jere @ 2019-11-23 16:50 UTC (permalink / raw)


On Saturday, November 23, 2019 at 4:12:59 AM UTC-5, Randy Brukardt wrote:
> "Robert A Duff" wrote in message 
> > Jere writes:
> >
> >> Is there a particular aggregate that I can use to avoid
> >> the superfluous wrapper record?
> >
> > See AI12-0212-1.TXT.  Not yet implemented in GNAT,
> > as far as I know.
> 
> If you wanted the indexes in order, you could use AI12-0061-1 (but I don't 
> know if that is implemented in GNAT yet, either):
> 
>      (for I in 1 .. 10 => (D => I, others => <>))
> 
> That still needs the wrapper record as I don't think you can write an 
> aggregate for a task. But a lot shorter.
> 
>                                         Randy.

yeah, I think I shot myself in the foot by trying to make the 
example as simple as possible.  My issue wasn't how to generate
the discriminants but simply how to initialize the task types
that had discriminants.  I mentioned in a separate email that
the real sceanrio is configuration values defined by enumerations
that change how the task works in slight ways.  They wouldn't be
unique or in any order.

My hope was that since Ada is so strongly typed I could have
done something like T'(D => Some_Option) and Ada would know
that since T is a task type it could correctly distinguish
it wasn't a record type instead.  At least GNAT cannot.

The wrapper record feels superfluous.  I"m not creating it because
it illustrates my design.  I'm using it because I don't know
a better way to initialize the type.

Thanks either way though

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

* Re: Initializing an array of tasks with discrimants
  2019-11-22 22:07 Initializing an array of tasks with discrimants Jere
                   ` (2 preceding siblings ...)
  2019-11-23  8:29 ` Dmitry A. Kazakov
@ 2019-11-23 16:57 ` Jere
  2019-11-25 22:36   ` Randy Brukardt
  3 siblings, 1 reply; 13+ messages in thread
From: Jere @ 2019-11-23 16:57 UTC (permalink / raw)


On Friday, November 22, 2019 at 5:07:49 PM UTC-5, Jere wrote:
> I recently ran into a situation where I had an array
> of tasks that had discriminants (with a default), but 
> I couldn't find a simple way to initialize them.  I 
> did come up with a workaround, but wanted to see if
> the language defined a way to do this:
> 
>     task type T(D: Integer := 3);
>     
>     task body T is 
>     begin 
>         null; 
>     end T;
>     
>     type A is array (Integer range <>) of T;
>     
>     V : A(1..10) := ?????????
> 
> If they all had the same discriminant value, I
> can just create a subtype and do an array of 
> the subtype, but in this case, the discriminants
> would not all be the same.
> 
> My work around was a wrapper type:
> 
>     type Wrapper(D : Integer := 0) is record
>         Impl : T(D);
>     end record.
> 
>     type A is array (Integer range <>) of Wrapper;
> 
>     V : A(1..10) := (1 => (D => 1, others => <>), and so on
> 
> But I was hoping there was a better way to do it simply.
> The Wrapper record isn't there to represent the 
> intended design and doesn't really improve readability.
> It's essentially a workaround for something I cannot 
> figure out.
> 
> I tried many variations of qualified expressions and 
> aggregates on the original task type elements, but all
> of them gave me errors about it expected the task type
> but found a composite type instead.
> 
> Is there a particular aggregate that I can use to avoid
> the superfluous wrapper record?

One other option I didn't think of which is definitely 
better than the wrapper record is a constructing function:

   function Make_Task(Option : Integer) return T is
   begin
      return Result : Task(Option);
   end Make_Task;

That lets me do things like:

   A : T_Array(1..10) :=
      (1 => Make_Task(2),
       2 => Make_Task(5),
       others => Make_Task(20));

I still think Ada should support aggregates for Tasks
with discriminants in some form.  I'm hoping the 2020 
change mentioned earlier will help with that (though I
never identified how when reading over it...I'll spend
some more time looking for it).

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

* Re: Initializing an array of tasks with discrimants
  2019-11-23 16:28   ` Jere
@ 2019-11-23 17:03     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2019-11-23 17:03 UTC (permalink / raw)


On 2019-11-23 17:28, Jere wrote:

> Yes, for ID's.  I really dialed down the example
> code for simplicity.  The actual scenario isn't
> ID's but a set of enumerations that provide
> configuration data for the tasks.

Then you should rather ask when Ada will get user-defined constructors 
and user-defined aggregates.

The former is required to determine task discriminants from whatever set 
of parameters ("virtual disciminants") you please.

The latter is required to initialize array using a procedure handing a 
list of whatever "virtual" elements.

> I was mostly just seeing
> if I could do away with the wrapper record for
> initialization.

And make your program unstable because of using hideous kludges no Ada 
vendor will ever make work same way in two consecutive compiler versions?

I would rather stay safe: Ada 95 + interfaces (where needed) + prefix 
notation (where needed), no fancy stuff.

Good old task initialization patterns:

1. Start entry

    task type T is
       entry Start (whatever parameters);
       ...
    end T;

    V : A (1..10);
begin
    V (1).Start (...);
    V (2).Start (...);
    ...

2. Task parameters factory object, e.g. passed as an access discriminant.

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


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

* Re: Initializing an array of tasks with discrimants
  2019-11-23 16:57 ` Jere
@ 2019-11-25 22:36   ` Randy Brukardt
  0 siblings, 0 replies; 13+ messages in thread
From: Randy Brukardt @ 2019-11-25 22:36 UTC (permalink / raw)


"Jere" <jhb.chat@gmail.com> wrote in message 
news:371cb59c-1814-4953-9652-43c9986808a1@googlegroups.com...
...
> I still think Ada should support aggregates for Tasks
> with discriminants in some form.  I'm hoping the 2020
> change mentioned earlier will help with that (though I
> never identified how when reading over it...I'll spend
> some more time looking for it).

We tried defining aggregates for all types in Ada 2005, but there were a 
number of semantic issues that prevented it from working out. One of them 
was with tasks, but I don't recall the details. I do think it could have 
been worked out, but the model was getting very complex and that can be an 
issue itself.

As previously noted by Bob, user-defined aggregates could probably be used 
to provide this capabillity for a particular task type. They can be applied 
to any non-array type, so one could use them to define an aggregate for for 
a task type. Probably would take some imagination, though, since the pattern 
for them is array aggregates (not records).

                                                                   Randy.




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

end of thread, other threads:[~2019-11-25 22:36 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-22 22:07 Initializing an array of tasks with discrimants Jere
2019-11-22 22:39 ` Jeffrey R. Carter
2019-11-23 16:23   ` Jere
2019-11-22 23:57 ` Robert A Duff
2019-11-23  0:27   ` Anh Vo
2019-11-23  9:12   ` Randy Brukardt
2019-11-23 16:50     ` Jere
2019-11-23 16:25   ` Jere
2019-11-23  8:29 ` Dmitry A. Kazakov
2019-11-23 16:28   ` Jere
2019-11-23 17:03     ` Dmitry A. Kazakov
2019-11-23 16:57 ` Jere
2019-11-25 22:36   ` Randy Brukardt

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