4
votes

I have a problem in Ada concurrent programming. I have to write a simple program in Ada that creates N of tasks of the same type, where N is the input from keyboard. The problem is that I have to know N before compilation... I have tried to declare a separate type:

TYPE my_arr IS ARRAY(INTEGER RANGE <>) OF some_task;

and later in BEGIN section of main procedure:

DECLARE arr: my_arr(1 .. N);

but I get the error

unconstrained element type in array declaration

Which (I think) means that task type some_task is of unknown size. Can anyone please help ?

3
It would help to see the definition of some_task. Does it have any discriminants, for example? - egilhh

3 Answers

3
votes

This is a rewrite of the original answer, now that we know that the task type in question is discriminated.

You are passing a value to each task via a 'discriminant' without a default, which makes the task type unconstrained; you can't declare an object of the type without supplying a value for the discriminant (and supplying a default wouldn't help, because once the object has been created the discriminant can't be changed).

One common approach to this uses access types:

with Ada.Integer_Text_IO;
with Ada.Text_IO;
procedure Maciek is
   task type T (Param : Integer);
   type T_P is access T;
   type My_Arr is array (Integer range <>) of T_P;
   task body T is
   begin
      Ada.Text_IO.Put_Line ("t" & Param'Img);
   end T;
   N, M : Integer;
begin
   Ada.Text_IO.Put ("number of tasks: ");
   Ada.Integer_Text_IO.Get (N);
   Ada.Text_IO.Put ("parameter: ");
   Ada.Integer_Text_IO.Get (M);
   declare
      --  Create an array of the required size and populate it with
      --  newly allocated T's, each constrained by the input
      --  parameter.
      Arr : My_Arr (1 .. N) := (others => new T (Param => M));
   begin
      null;
   end;
end Maciek;

You may need to deallocate the newed tasks once they are completed; in the code above, the tasks' memory is leaked on exit from the declare block.

2
votes

Allocate them in a 'declare block', or dynamically allocate them:

   type My_Arr is array (Integer range <>) of Some_Task;

   type My_Arr_Ptr is access My_Arr;

   Arr : My_Arr_Ptr;

begin
   -- Get the value of N

   -- Dynamic allocation
   Arr := new My_Arr(1 .. N);

   declare
      Arr_On_Stack : My_Arr(1 .. N);

   begin
      -- Do stuff
   end;

end;
0
votes

If you are sure at runtime, how many tasks you want, you can pass that as command-line argument.

with Ada.Text_IO; use ADA.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Command_Line;
with Ada.Strings;

procedure multiple_task is

    No_of_tasks : Integer := Integer'Value(Ada.Command_Line.Argument(1));

    task type Simple_tasks;

    task body Simple_tasks is
    begin
        Put_Line("I'm a simple task");
    end Simple_tasks;

    type task_array is array (Integer range <>) of Simple_tasks;

    Array_1 : task_array(1 .. No_of_tasks);

begin
   null;

end multiple_task;

And run as

> multiple_task.exe 3
I'm a simple task
I'm a simple task
I'm a simple task