Reputation: 15
Are nested "then abort" constructions legal in Ada? If yes, how properly can I use them? I have this code:
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
task TestTask is
end TestTask;
task body TestTask is
begin
select
delay 2.0;
Put_Line("C"); -- never executed
then abort
select
delay 5.0;
then abort
Put_Line("A");
delay 4.0;
end select;
loop
Put_Line("B");
delay 10.0;
end loop;
end select;
end TestTask;
begin
null;
end Main;
I expect that this code should exit after 2 seconds. But instead, it prints continuously "B" without even delay (it ignores delay 10.0
). It looks that code behaves in this way:
Put_Line("A")
and wait 2 secondsdelay 10.0
If instead of delay 4.0
we insert delay 1.0
(then aborting occurs inside the loop), the program works properly. I think it is very dangerous, because "abort then" can be inside library function, for example:
procedure Main is
----- It's function from library -----
procedure Foo is
begin
select
delay 5.0;
then abort
Put_Line("A");
delay 4.0;
end select;
end;
---------------------------------------
task TestTask is
end TestTask;
task body TestTask is
begin
select
delay 2.0;
Put_Line("C"); -- never executed
then abort
Foo;
loop
Put_Line("B");
delay 10.0;
end loop;
end select;
end TestTask;
begin
null;
end Main;
Can someone explain why this program behaves in this weird way?
Upvotes: 1
Views: 173
Reputation: 205865
As noted in A Comparison of the Asynchronous Transfer of Control Features in Ada and the Real-Time Specification, "The asynchronous select statement deals with nested ATCs correctly. For example, if the delay for an outer triggering statement expires while an inner delay is pending, the inner delay will be canceled and an ATC will be promulgated out of the inner abortable part…"
The variation below prints ABBBBC
, as expected. The outer triggering statement specifies a five second timeout; the nested triggering statement specifies a three second timeout. As the latter's abortable part only consumes one second of its thee second budget, the ensuing loop
can print four B's before the outer timeout. Change the outer delay
to 1.0
in order to reproduce the effect seen in your example.
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
task TestTask;
task body TestTask is
begin
select
delay 5.0;
Put("C");
then abort
select
delay 3.0;
then abort
Put("A");
delay 1.0;
end select;
loop
Put("B");
delay 1.0;
end loop;
end select;
end TestTask;
begin
null;
end Main;
Upvotes: 3