0
votes

I'm trying to execute all procedures stored in an array concurrently but with no success. I can execute them sequentially:

with ada.text_io;   -- Tell compiler to use i/o library
use  ada.text_io;   -- Use library routines w/o fully qualified names

with Ada.Numerics.Float_Random; -- Use numerics for the random generation
use ada.Numerics.Float_Random;

procedure Main is

   type Callback_Procedure is access procedure; -- Type that contains a procedure pointer
   type arr is array (Natural range <>) of Callback_Procedure; -- Array starting from 0 toi infinite of procedure pointers
   seed : Generator; -- Seed for the generator

   -- Procedure that will execute "concurrently" the procedures passed in the array
   procedure EjecutarConcurrentemente(procs : in arr ) is
   begin

      for index in 0 .. procs'Last loop

         procs(index).all; -- .all dereferences the pointer so it is the procedure itself (the value pointed by the pointer)

      end loop;      

   end EjecutarConcurrentemente;

   function rndDelay return Duration is
      num : Duration;
   begin
      num := Duration(Random(seed));
      return num * Duration(10);
   end ;


   procedure test0 is
   begin
      delay rndDelay;
      put("test0");
      New_Line;
   end test0;

   procedure test1 is
   begin
      delay rndDelay;
      put("test1");
      New_Line;
   end test1;

   procedure test2 is
   begin
      delay rndDelay;
      put("test2");
      New_Line;
   end test2;

   procedure test3 is
   begin
      delay rndDelay;
      put("test3");
      New_Line;
   end test3;

   procedure test4 is
   begin
      delay rndDelay;
      put("test4");
      New_Line;
   end test4;

   procedure test5 is
   begin
      delay rndDelay;
      put("test5");
      New_Line;
   end test5;

   procs : arr(0..5);

begin

   Reset(seed);

   procs(0) := test0'Access;
   procs(1) := test1'Access;
   procs(2) := test2'Access;
   procs(3) := test3'Access;
   procs(4) := test4'Access;
   procs(5) := test5'Access;

   EjecutarConcurrentemente(procs);

end Main;

The Main procedure body populates an array with 6 procedures declared before and the calls EjecutarConcurrentemente with that array and it must be this new procedure who has to execute the array procedures concurrently.

I've been told to use the Task functionalities, and the testX must be procedures without arguments.

Hope I have explained it well, also I have just started with Ada, so the code will most likely be bad formed.

Thanks.

2
Why would the number of arguments to the testX procedures prevent usage of tasks? - egilhh
“Concurrently" with what? the main program? (easy-ish), each other? (difficult). - Simon Wright
@egilhh I'm not saying that, I just say that it is a requisite - J. Arenas
@SimonWright the tasks in the array must be concurrent with each other in said array - J. Arenas
@J.Arenas then you probably meant "and" instead of "but"? - egilhh

2 Answers

2
votes

Whoever told you to use tasks for concurrent execution gave you the right answer. To run all six procedures concurrently, you need six tasks (and six processors/processor cores).

1
votes

Here is the code working perfectly:

with ada.text_io;   -- Tell compiler to use i/o library
use  ada.text_io;   -- Use library routines w/o fully qualified names

with Ada.Numerics.Float_Random; -- Use numerics for the random generation
use ada.Numerics.Float_Random;

procedure Main is

   type Callback_Procedure is access procedure; -- Type that contains a procedure pointer
   type arr is array (Natural range <>) of Callback_Procedure; -- Array starting from 0 toi infinite of procedure pointers
   seed : Generator; -- Seed for the generator

   task type Ex (proc : Callback_Procedure);
   type A is access Ex;

   task body Ex is
   begin
      proc.all; --.all dereferences the pointer so it is the procedure itself (the value pointed by the pointer)
   end Ex;

   -- Procedure that will execute concurrently the procedures passed in the array
   procedure EjecutarConcurrentemente(procs : in arr ) is
      p : A;
   begin

      for index in 0 .. procs'Last loop

         p := new Ex(procs(index));

      end loop;      

   end EjecutarConcurrentemente;

   function rndDelay return Duration is
      num : Duration;
   begin
      num := Duration(Random(seed));
      return num * Duration(10);
   end ;


   procedure test0 is
   begin
      delay rndDelay;
      put("test0");
      New_Line;
   end test0;

   procedure test1 is
   begin
      delay rndDelay;
      put("test1");
      New_Line;
   end test1;

   procedure test2 is
   begin
      delay rndDelay;
      put("test2");
      New_Line;
   end test2;

   procedure test3 is
   begin
      delay rndDelay;
      put("test3");
      New_Line;
   end test3;

   procedure test4 is
   begin
      delay rndDelay;
      put("test4");
      New_Line;
   end test4;

   procedure test5 is
   begin
      delay rndDelay;
      put("test5");
      New_Line;
   end test5;

   procs : arr(0..5);

begin

   Reset(seed);

   procs(0) := test0'Access;
   procs(1) := test1'Access;
   procs(2) := test2'Access;
   procs(3) := test3'Access;
   procs(4) := test4'Access;
   procs(5) := test5'Access;

   EjecutarConcurrentemente(procs);

end Main;

I just make a Task with a procedure pointer as parameter, then in the array loop I do

new Ex(procs(index));

and it instantly starts a new Task with the given procedure