Reputation: 740
How can I get these tasks run concurrently, so that the "Hello World from N" messages will be mixed up?
My output looks always like this except that 1, 2 or 3 can be interchanged.
Hello World from 1!
Hello World from 2!
Hello World from 3!
It does not look like the tasks run concurrently. It looks like it run in a chain on a first-come, first-served basis.
main.adb
with Ada.Text_IO;
procedure Main is
type Runnable_Type is access procedure;
task type Filter (Runnable_Access : Runnable_Type) is
entry start;
end Filter;
task body Filter is
begin
accept start;
Runnable_Access.all;
end Filter;
procedure Run_1 is
begin
Ada.Text_IO.Put_Line ("Hello World from 1!");
end Run_1;
procedure Run_2 is
begin
Ada.Text_IO.Put_Line ("Hello World from 2!");
end Run_2;
procedure Run_3 is
begin
Ada.Text_IO.Put_Line ("Hello World from 3!");
end Run_3;
Filter_1 : Filter (Run_1'Access);
Filter_2 : Filter (Run_2'Access);
Filter_3 : Filter (Run_3'Access);
begin
Filter_1.start;
Filter_2.start;
Filter_3.start;
end Main;
Upvotes: 2
Views: 308
Reputation: 63
As Jack notes, they are run concurrently. Putting a busy-loop in different parts of the Run_* procedures shows this.
with Ada.Text_IO;
procedure Main is
type Runnable_Type is access procedure;
task type Filter (Runnable_Access : Runnable_Type) is
entry start;
end Filter;
task body Filter is
begin
accept start;
Runnable_Access.all;
end Filter;
procedure Run_1 is
counter : integer := 0;
begin
for i in 1..1000000 loop
counter := counter + 1;
end loop;
Ada.Text_IO.Put_Line ("Hello World from 1a!");
Ada.Text_IO.Put_Line ("Hello World from 1b!");
Ada.Text_IO.Put_Line ("Hello World from 1c!");
end Run_1;
procedure Run_2 is
counter : integer := 0;
begin
Ada.Text_IO.Put_Line ("Hello World from 2a!");
for i in 1..1000000 loop
counter := counter + 1;
end loop;
Ada.Text_IO.Put_Line ("Hello World from 2b!");
Ada.Text_IO.Put_Line ("Hello World from 2c!");
end Run_2;
procedure Run_3 is
counter : integer := 0;
begin
Ada.Text_IO.Put_Line ("Hello World from 3a!");
Ada.Text_IO.Put_Line ("Hello World from 3b!");
for i in 1..1000000 loop
counter := counter + 1;
end loop;
Ada.Text_IO.Put_Line ("Hello World from 3c!");
end Run_3;
Filter_1 : Filter (Run_1'Access);
Filter_2 : Filter (Run_2'Access);
Filter_3 : Filter (Run_3'Access);
begin
Filter_1.start;
Filter_2.start;
Filter_3.start;
end Main;
Output is:
Hello World from 2a!
Hello World from 3a!
Hello World from 3b!
Hello World from 2b!
Hello World from 2c!
Hello World from 1a!
Hello World from 1b!
Hello World from 1c!
Hello World from 3c!
Upvotes: 1
Reputation: 31699
Using Text_IO.Put_Line
will most likely cause the entire line to be written in one operation, although it's plausible that it might be two operations (one to output the characters in the string, and one to output the newline). But the OS call to output the string (possibly without the newline) is probably one call, and the OS operation may be be uninterruptible, or it may go so fast that it would be very difficult to interrupt with a thread switch. In any event, this probably does not output one character at a time. (I'm assuming you're running on a Linux or Windows system or similar, as opposed to an embedded system with a minimal runtime or the like.)
You could output one character at a time yourself:
procedure Output_String (S : String) is
begin
for I in S'range loop
Text_IO.Put (S (I));
--delay 0.0;
end loop;
Text_IO.New_Line;
end Output_String;
and then have your Run
procedures call this instead of Text_IO.Put_Line
. If it doesn't work without delay 0.0
, try it with this delay instead, as it may cause the program to look for some other ready task of the same priority to run. I'm not guaranteeing anything, though.
Upvotes: 3
Reputation: 609
The tasks are running concurrently. They're just not doing enough for this concurrency to be visible. Add more work to each task, e.g. repeatedly printing out a line of text, and you will see it.
Upvotes: 3