with System.Storage_Pools;
with System.Storage_Elements;

package Asl.Leak_Detect_Pool is

   type Leak_Pool is new System.Storage_Pools.Root_Storage_Pool with private;

   procedure Allocate
     (Pool         : in out Leak_Pool;
      Address      : out System.Address;
      Storage_Size : in System.Storage_Elements.Storage_Count;
      Alignment    : in System.Storage_Elements.Storage_Count);

   procedure Deallocate
     (Pool         : in out Leak_Pool;
      Address      : in System.Address;
      Storage_Size : in System.Storage_Elements.Storage_Count;
      Alignment    : in System.Storage_Elements.Storage_Count);

   function Storage_Size (Pool : Leak_Pool)
                          return System.Storage_Elements.Storage_Count;

   Deallocate_Of_Invalid_Data : exception;

   type End_Marker is (Past_End, Not_Past_End);

   type Iterator is private;

   -- Go to the first element in the pool.  Iter will be set to Past_End if
   -- the pool is empty.  Otherwise, the address and size will be returned.
   procedure First (Pool    : in Leak_Pool;
                    Iter    : in out Iterator;
                    Is_End  : out End_Marker;
                    Address : out System.Address;
                    Size    : out System.Storage_Elements.Storage_Count);

   -- Go to the next element in the pool.  Iter will be set to Past_End if
   -- at the pool end.  Otherwise, the address and size will be returned.
   procedure Next (Iter    : in out Iterator;
                   Is_End  : out End_Marker;
                   Address : out System.Address;
                   Size    : out System.Storage_Elements.Storage_Count);

private

   use type System.Storage_Elements.Storage_Count;

   type Magic_Number is mod 2 ** 32;
   for Magic_Number'Size use 32;

   Leak_Pool_Magic : constant Magic_Number := 16#80fdb14c#;

   type Alloc_Data is array (System.Storage_Elements.Storage_Count range <>) of
     aliased System.Storage_Elements.Storage_Element;
   for Alloc_Data'Alignment use 4;
   type Alloc_Data_Ptr is access all Alloc_Data;

   type Pool_Element;
   type Pool_Element_Ptr is access all Pool_Element;
   type Pool_Element is record
      Magic     : Magic_Number;
      Size      : System.Storage_Elements.Storage_Count;
      Real_Size : System.Storage_Elements.Storage_Count;
      Next      : Pool_Element_Ptr;
      Prev      : Pool_Element_Ptr;
   end record;

   type Leak_Pool is new System.Storage_Pools.Root_Storage_Pool with record
      Elements : Pool_Element_Ptr := null;
   end record;

   type Iterator is record
      Curr : Pool_Element_Ptr;
   end record;

end Asl.Leak_Detect_Pool;