Search code examples
arraysgenericscontainersadavariant

Ada -- Array of queues of unconstrained objects results in Storage_Error -- How to resolve?


So, disclaimer, I've only been using Ada for a few weeks now... I expect to have a noob mistake causing this.

So the (anonymized) code I have...

with Ada.Text_IO; use Ada.Text_IO;

with Ada.Containers.Synchronized_Queue_Interfaces;
with Ada.Containers.Bounded_Synchronized_Queues;

procedure Hello is
  type ID_Type is ( Invalid_Id,
                    Config_Id);

  for ID_Type use ( Invalid_Id => 16#00#,
                    Config_Id => 16#11#  );
  for ID_Type'Size use 8;                  

  type Config_Type is 
    record
      data : Integer;
    end record;

  type Data_Type (i : ID_Type := Invalid_Id) is 
    record
      Id : ID_Type := i;

      case i is
        when Invalid_Id => null;
        when Config_Id => config : Config_Type;
        when others => null;
      end case; 
    end record with Unchecked_Union, Convention => C;

  package Queue_Interface is
    new Ada.Containers.Synchronized_Queue_Interfaces(Data_Type);

  package Data_Queue is 
    new Ada.Containers.Bounded_Synchronized_Queues
      ( Queue_Interfaces => Queue_Interface,
        Default_Capacity => 1);

  Queue_Array : array(1..1) of Data_Queue.Queue;

begin

  Put_Line("Queue_Array(1)'Size = " & Integer'Image(Queue_Array(1)'Size));

end Hello;

On the online compiler (GNAT 7.1.1) this triggers: raised STORAGE_ERROR : s-intman.adb:136 explicit raise

Intended use is to interface with C-level drivers pulling data from serial port. (Hence the unchecked_union and other representation clauses)

Have tried wrapping with an Indefinite_Holder assuming the indefinite issue was from the Unconstrained type... and was getting the same error. Thought that I wouldn't need it because while it's an unconstrained variant it is definite in size. Same thing either way though.

Also worth noting that: test1 : array (ID_Type) Data_Type; -- works test2 : Data_Queue.Queue; -- works test3 : array (1 .. 2) Data_Queue.Queue; -- Storage_Error

What am I doing wrong?


Solution

  • The definition of the Bounded_Synchronized_Queue is

     protected type Queue
        (Capacity : Count_Type := Default_Capacity;
         Ceiling  : System.Any_Priority := Default_Ceiling)
           with Priority => Ceiling is
        new Queue_Interfaces.Queue
    

    It looks like GNAT is trying to allocate size for all potential permutations of array sizes, leading to an extremely large sized type. Since this is a limited type, I'm not sure if it still has to do that or not (so may be a bug).

    You can fix it by changing the declaration's discriminant to have a specific constraint:

    -- create an array of queues
    Queue_Array : array(ID_Type) of ID_Holder_Queue.Queue
        (Capacity => 16,
         Ceiling  => System.Priority'Last);
    

    and withing System;

    That should remove your storage error. This might be related if you are using the GNAT compiler.