comp.lang.ada
 help / color / mirror / Atom feed
* Select + Accept syntax question
@ 2016-08-27 18:26 Andrew Shvets
  2016-08-27 19:20 ` Niklas Holsti
  2016-08-27 19:36 ` Jeffrey R. Carter
  0 siblings, 2 replies; 7+ messages in thread
From: Andrew Shvets @ 2016-08-27 18:26 UTC (permalink / raw)


Hello,

When working with tasks, you can use a selective wait in order to have your task quickly check its queue of messages and see if there any waiting for it (i.e. a selective wait.)  Now, in order to further build on this, guards can be used to ensure that certain conditions are met before processing some messages.

After messing around with both concepts, I created the following example:
while Go_Loop LOOP
  select
    when Internal_Value = 0 =>
      accept Input(Value : in Integer) do
        Internal_Value := Value;
      end Input;
  or
    when Internal_Value /= 0 =>
      accept Retrieve(Value : out Integer) do
        Value := Internal_Value;
      end Retrieve;

The one thing that threw me for a loop was when I put any type of code right before the above two accept keywords, like so:
while Go_Loop LOOP
  select
    when Internal_Value = 0 =>
      Ada.Text_IO.Put_Line("hello world");
      accept Input(Value : in Integer) do
        Internal_Value := Value;
      end Input;
  or
    when Internal_Value /= 0 =>
      Ada.Text_IO.Put_Line("hello world");
      accept Retrieve(Value : out Integer) do
        Value := Internal_Value;
      end Retrieve;

And I get the following output from the compiler:

> gnatmake -g .\task_demo_11.adb
gcc -c -I.\ -g -I- .\task_demo_11.adb
task_demo_11.adb:25:16: missing "END SELECT;" for "SELECT" at line 18
task_demo_11.adb:25:17: select alternative ("ACCEPT", "ABORT", "DELAY") expected
task_demo_11.adb:38:07: "OR" not allowed here
task_demo_11.adb:42:07: no "SELECT" for this "END SELECT"
gnatmake: ".\task_demo_11.adb" compilation error

Why does this happen?  Why can't I have code right before the accept?  I can see a compilation error if there is no accept...


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

* Re: Select + Accept syntax question
  2016-08-27 18:26 Select + Accept syntax question Andrew Shvets
@ 2016-08-27 19:20 ` Niklas Holsti
  2016-08-27 19:47   ` Andrew Shvets
  2016-08-27 19:36 ` Jeffrey R. Carter
  1 sibling, 1 reply; 7+ messages in thread
From: Niklas Holsti @ 2016-08-27 19:20 UTC (permalink / raw)


On 16-08-27 21:26 , Andrew Shvets wrote:

> The one thing that threw me for a loop was when I put any type of code right before the above two accept keywords, like so:
> while Go_Loop LOOP
>   select
>     when Internal_Value = 0 =>
>       Ada.Text_IO.Put_Line("hello world");
>       accept Input(Value : in Integer) do
>         Internal_Value := Value;
>       end Input;
>   or
>     when Internal_Value /= 0 =>
>       Ada.Text_IO.Put_Line("hello world");
>       accept Retrieve(Value : out Integer) do
>         Value := Internal_Value;
>       end Retrieve;
>
> And I get the following output from the compiler:
>
>> gnatmake -g .\task_demo_11.adb
> gcc -c -I.\ -g -I- .\task_demo_11.adb
> task_demo_11.adb:25:16: missing "END SELECT;" for "SELECT" at line 18
> task_demo_11.adb:25:17: select alternative ("ACCEPT", "ABORT", "DELAY") expected
> task_demo_11.adb:38:07: "OR" not allowed here
> task_demo_11.adb:42:07: no "SELECT" for this "END SELECT"
> gnatmake: ".\task_demo_11.adb" compilation error
>
> Why does this happen?  Why can't I have code right before the accept?

Before I try to answer that question, I would like to know what 
behaviour you expect from such code. In particular, exactly when would 
that code be executed?

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


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

* Re: Select + Accept syntax question
  2016-08-27 18:26 Select + Accept syntax question Andrew Shvets
  2016-08-27 19:20 ` Niklas Holsti
@ 2016-08-27 19:36 ` Jeffrey R. Carter
  2016-08-27 19:48   ` Andrew Shvets
  1 sibling, 1 reply; 7+ messages in thread
From: Jeffrey R. Carter @ 2016-08-27 19:36 UTC (permalink / raw)


On 08/27/2016 11:26 AM, Andrew Shvets wrote:
> 
> Why does this happen?  Why can't I have code right before the accept?  I can
> see a compilation error if there is no accept...

The definition of a selective accept doesn't allow this. This definition is in
ARM 9.7.1(2-7)

http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-9-7-1.html

2
selective_accept ::=
  select
   [guard]
     select_alternative
{ or
   [guard]
     select_alternative }
[ else
   sequence_of_statements ]
  end select;
3
guard ::= when condition =>
4
select_alternative ::=
   accept_alternative
  | delay_alternative
  | terminate_alternative
5
accept_alternative ::=
  accept_statement [sequence_of_statements]
6
delay_alternative ::=
  delay_statement [sequence_of_statements]
7
terminate_alternative ::= terminate;

So the 1st thing after "select [guard]" or "or [guard]" has to be an accept,
delay, or terminate statement.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail
09


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

* Re: Select + Accept syntax question
  2016-08-27 19:20 ` Niklas Holsti
@ 2016-08-27 19:47   ` Andrew Shvets
  2016-08-28  6:52     ` Niklas Holsti
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Shvets @ 2016-08-27 19:47 UTC (permalink / raw)


On Saturday, August 27, 2016 at 3:20:16 PM UTC-4, Niklas Holsti wrote:
> On 16-08-27 21:26 , Andrew Shvets wrote:
> 
> > The one thing that threw me for a loop was when I put any type of code right before the above two accept keywords, like so:
> > while Go_Loop LOOP
> >   select
> >     when Internal_Value = 0 =>
> >       Ada.Text_IO.Put_Line("hello world");
> >       accept Input(Value : in Integer) do
> >         Internal_Value := Value;
> >       end Input;
> >   or
> >     when Internal_Value /= 0 =>
> >       Ada.Text_IO.Put_Line("hello world");
> >       accept Retrieve(Value : out Integer) do
> >         Value := Internal_Value;
> >       end Retrieve;
> >
> > And I get the following output from the compiler:
> >
> >> gnatmake -g .\task_demo_11.adb
> > gcc -c -I.\ -g -I- .\task_demo_11.adb
> > task_demo_11.adb:25:16: missing "END SELECT;" for "SELECT" at line 18
> > task_demo_11.adb:25:17: select alternative ("ACCEPT", "ABORT", "DELAY") expected
> > task_demo_11.adb:38:07: "OR" not allowed here
> > task_demo_11.adb:42:07: no "SELECT" for this "END SELECT"
> > gnatmake: ".\task_demo_11.adb" compilation error
> >
> > Why does this happen?  Why can't I have code right before the accept?
> 
> Before I try to answer that question, I would like to know what 
> behaviour you expect from such code. In particular, exactly when would 
> that code be executed?
> 
> -- 
> Niklas Holsti
> Tidorum Ltd
> niklas holsti tidorum fi
>        .      @       .

To print something out and then wait for a message to arrive.


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

* Re: Select + Accept syntax question
  2016-08-27 19:36 ` Jeffrey R. Carter
@ 2016-08-27 19:48   ` Andrew Shvets
  2016-08-27 23:22     ` Jeffrey R. Carter
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Shvets @ 2016-08-27 19:48 UTC (permalink / raw)


On Saturday, August 27, 2016 at 3:36:35 PM UTC-4, Jeffrey R. Carter wrote:
> On 08/27/2016 11:26 AM, Andrew Shvets wrote:
> > 
> > Why does this happen?  Why can't I have code right before the accept?  I can
> > see a compilation error if there is no accept...
> 
> The definition of a selective accept doesn't allow this. This definition is in
> ARM 9.7.1(2-7)
> 
> http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-9-7-1.html
> 
> 2
> selective_accept ::=
>   select
>    [guard]
>      select_alternative
> { or
>    [guard]
>      select_alternative }
> [ else
>    sequence_of_statements ]
>   end select;
> 3
> guard ::= when condition =>
> 4
> select_alternative ::=
>    accept_alternative
>   | delay_alternative
>   | terminate_alternative
> 5
> accept_alternative ::=
>   accept_statement [sequence_of_statements]
> 6
> delay_alternative ::=
>   delay_statement [sequence_of_statements]
> 7
> terminate_alternative ::= terminate;
> 
> So the 1st thing after "select [guard]" or "or [guard]" has to be an accept,
> delay, or terminate statement.
> 
> -- 
> Jeff Carter
> "Monsieur Arthur King, who has the brain of a duck, you know."
> Monty Python & the Holy Grail
> 09

I see, thank you.

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

* Re: Select + Accept syntax question
  2016-08-27 19:48   ` Andrew Shvets
@ 2016-08-27 23:22     ` Jeffrey R. Carter
  0 siblings, 0 replies; 7+ messages in thread
From: Jeffrey R. Carter @ 2016-08-27 23:22 UTC (permalink / raw)


On 08/27/2016 12:48 PM, Andrew Shvets wrote:
> On Saturday, August 27, 2016 at 3:36:35 PM UTC-4, Jeffrey R. Carter wrote:
>>
>> So the 1st thing after "select [guard]" or "or [guard]" has to be an accept,
>> delay, or terminate statement.
> 
> I see, thank you.

Your next question, and what Holsti's was trying to get you to consider (I
think), is why it's defined this way. It's important to remember that a
selective accept can have more than 1 open accept alternative. An example of
this is given at the end of ARM 9.7.1:

24
task body Server is
   Current_Work_Item : Work_Item;
begin
   loop
      select
         accept Next_Work_Item(WI : in Work_Item) do
            Current_Work_Item := WI;
         end;
         Process_Work_Item(Current_Work_Item);
      or
         accept Shut_Down;
         exit;       -- Premature shut down requested
      or
         terminate;  -- Normal shutdown at end of scope
      end select;
   end loop;
end Server;

Now, suppose we put a Put_Line immediately prior to each accept, and that such a
statement were legal. When the task reaches the select, how does it decide which
Put_Line to execute? When does it make that decision? When does it execute the
chosen Put_Line? Remember, there may be calls waiting to either, both, or
neither of the entries.

Now, if you're going to allow one statement there, you might as well allow 2,
and if you allow 2, you might as well allow 3, and if you allow 3, you might as
well allow any sequence of statements. Such a change would make the compiler
writer's job harder, as the compiler would have to search through the statements
to find the accept (or delay) that the task should use to decide if it can
select that branch. There might be multiple accepts, for multiple entries, in
different branches of an if. While it's a general rule of language design that
ease of use should have priority over ease of compiler writing, there are limits
to how difficult it can be to write a compiler for a language. In this case, it
doesn't seem that this feature would let you do anything you can't do without
it, so the extra complexity doesn't seem justified.

Another consideration is that, if the sequence of statements is long, at some
point down the line someone might mistakenly put an accept or delay in the
sequence, creating a logic error that might be difficult to find.

Your example is not really a good use of the selective accept, as it would be
better written

accept Input ...

loop
   accept Retrieve ...
end loop;

This version is much clearer and easy to understand. It also eliminates the use
of a magic value.

Since the introduction of protected objects in Ada 95, the use of task entries
and rendezvous is less common, with many tasks communicating through POs. If
what I've written above is all your task does, it would be much better
implemented as a PO.

I presume you're trying to learn about selective accepts. A good example for
that might be the concurrent Sieve of Eratosthenes, which sets up a pipeline of
tasks, each holding a discovered prime eliminating candidates that are multiples
of its prime. After all the potential candidates have been sieved, each task in
turn should be instructed to do something interesting with its prime, such as
output it.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail
09

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

* Re: Select + Accept syntax question
  2016-08-27 19:47   ` Andrew Shvets
@ 2016-08-28  6:52     ` Niklas Holsti
  0 siblings, 0 replies; 7+ messages in thread
From: Niklas Holsti @ 2016-08-28  6:52 UTC (permalink / raw)


On 16-08-27 22:47 , Andrew Shvets wrote:
> On Saturday, August 27, 2016 at 3:20:16 PM UTC-4, Niklas Holsti wrote:
>> On 16-08-27 21:26 , Andrew Shvets wrote:
>>
>>> The one thing that threw me for a loop was when I put any type of code right before the above two accept keywords, like so:
>>> while Go_Loop LOOP
>>>   select
>>>     when Internal_Value = 0 =>
>>>       Ada.Text_IO.Put_Line("hello world");
>>>       accept Input(Value : in Integer) do
>>>         Internal_Value := Value;
>>>       end Input;
>>>   or
>>>     when Internal_Value /= 0 =>
>>>       Ada.Text_IO.Put_Line("hello world");
>>>       accept Retrieve(Value : out Integer) do
>>>         Value := Internal_Value;
>>>       end Retrieve;
>>>
>>> And I get the following output from the compiler:
>>>
>>>> gnatmake -g .\task_demo_11.adb
>>> gcc -c -I.\ -g -I- .\task_demo_11.adb
>>> task_demo_11.adb:25:16: missing "END SELECT;" for "SELECT" at line 18
>>> task_demo_11.adb:25:17: select alternative ("ACCEPT", "ABORT", "DELAY") expected
>>> task_demo_11.adb:38:07: "OR" not allowed here
>>> task_demo_11.adb:42:07: no "SELECT" for this "END SELECT"
>>> gnatmake: ".\task_demo_11.adb" compilation error
>>>
>>> Why does this happen?  Why can't I have code right before the accept?
>>
>> Before I try to answer that question, I would like to know what
>> behaviour you expect from such code. In particular, exactly when would
>> that code be executed?
>>
>> --
>> Niklas Holsti
>> Tidorum Ltd
>> niklas holsti tidorum fi
>>        .      @       .
>
> To print something out and then wait for a message to arrive.

So the statement between the guard and the "accept" would be executed 
before the rendez-vous at the "accept"? And if several "or" alternatives 
are open (with True guards), all of their statements in this position 
would be executed before it is known which "accept" is selected for 
execution?

That would be against the intent of the "select"-"or" construct, where 
the point is to select and execute _one_ of the alternatives. And that 
is why the syntax insists that the conditions for choosing a particular 
alternative (the guard and the "accept" or other select-alternative) 
must appear together, with no statements in between.

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

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

end of thread, other threads:[~2016-08-28  6:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-27 18:26 Select + Accept syntax question Andrew Shvets
2016-08-27 19:20 ` Niklas Holsti
2016-08-27 19:47   ` Andrew Shvets
2016-08-28  6:52     ` Niklas Holsti
2016-08-27 19:36 ` Jeffrey R. Carter
2016-08-27 19:48   ` Andrew Shvets
2016-08-27 23:22     ` Jeffrey R. Carter

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