with GNATCOLL.JSON;
with Ada.Strings.Fixed;  use Ada.Strings.Fixed;

package body Smart_Impl is

   function Make_A_Json return GNATCOLL.JSON.JSON_Value
      is (GNATCOLL.JSON.Read("{""Hello"":""world""}"));

   --  20-100 seems to trigger errors quite often
   Max_Tasks : Integer := 128;

   task type Background_Task_Type is
     entry Do_The_Thing (An_Item : in  GNATCOLL.JSON.JSON_Value; My_Index : Integer);
   end Background_Task_Type;

   Background_Pool : array (1 .. Max_Tasks) of Background_Task_Type;

   task body Background_Task_Type is
      A : GNATCOLL.JSON.JSON_Value;
      N : Integer;
   begin
      loop
         select
            accept Do_The_Thing
               (An_Item : in  GNATCOLL.JSON.JSON_Value; My_Index : Integer)
            do
               A := An_Item;
               N := My_Index + 1;
            end Do_The_Thing;

            if N <= Max_Tasks then
               Background_Pool(N).Do_The_Thing(A, N);
            end if;

            -- need to clear or we just keep hold of json until termination
            A := GNATCOLL.JSON.JSON_Null;
         or
            terminate;
         end select;
      end loop;
   end Background_Task_Type;

   --  make stuff in the background to attempt to overwrite freed memory.

   task Maker_Task is
      entry Make_Lots;
   end Maker_Task;

   task body Maker_Task is
   begin
      loop
         select
            accept Make_Lots do
               null;
            end Make_Lots;

            for X in Integer range 1 .. 2_000 loop
               declare
                   X : GNATCOLL.JSON.JSON_Value;
                   pragma Unreferenced (X);
                begin
                   X := Make_A_Json;
                   X := GNATCOLL.JSON.JSON_Null;
                   X := Make_A_Json;
                   X := GNATCOLL.JSON.JSON_Null;
                   X := Make_A_Json;
                   X := GNATCOLL.JSON.JSON_Null;
                end;
            end loop;
         or
            terminate;
         end select;
      end loop;
   end Maker_Task;

   procedure Main is
   begin
      --  make stuff in the background to attempt to overwrite freed memory.
      Maker_Task.Make_Lots;

      Background_Pool(1).Do_The_Thing (Make_A_Json, 1);
   end Main;

end Smart_Impl;
