* 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 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: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
* 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: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
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