Aspect Storage_Model_Type (GNAT Reference Manual)

#### 17.3.3.1 Aspect Storage_Model_Type ¶

A Storage model is a type with a specified `Storage_Model_Type` aspect, e.g.:

    type A_Model is null record
       with Storage_Model_Type (...);

Storage_Model_Type itself accepts six parameters:

- Address_Type, the type of the address managed by this model. This has to be a scalar type or derived from System.Address.
- Allocate, a procedure used for allocating memory in this model
- Deallocate, a procedure used for deallocating memory in this model
- Copy_To, a procedure used to copy memory from native memory to this model
- Copy_From, a procedure used to copy memory from this model to native memory
- Storage_Size, a function returning the amount of memory left
- Null_Address, a value for the null address value

By default, Address_Type is System.Address, and the five subprograms perform native operations (e.g. the allocator is the native `new` allocator). Users can decide to specify one or more of these. When an Address_Type is specified to be other than System.Address, all of the subprograms have to be specified.

The prototypes of these procedures are as follows:

    procedure Allocate
      (Model           : in out A_Model;
       Storage_Address : out Address_Type;
       Size            : Storage_Count;
       Alignment       : Storage_Count);

    procedure Deallocate
      (Model           : in out A_Model;
       Storage_Address : out Address_Type;
       Size            : Storage_Count;
       Alignment       : Storage_Count);

    procedure Copy_To
      (Model   : in out A_Model;
       Target  : Address_Type;
       Source  : System.Address;
       Size    : Storage_Count);

    procedure Copy_From
      (Model  : in out A_Model;
       Target : System.Address;
       Source : Address_Type;
       Size   : Storage_Count);

    function Storage_Size
      (Pool : A_Model)
       return Storage_Count;

Here’s an example of how this could be instantiated in the context of CUDA:

    package CUDA_Memory is

       type CUDA_Storage_Model is null record
          with Storage_Model_Type => (
             Address_Type => CUDA_Address,
             Allocate     => CUDA_Allocate,
             Deallocate   => CUDA_Deallocate,
             Copy_To      => CUDA_Copy_To,
             Copy_From    => CUDA_Copy_From,
             Storage_Size => CUDA_Storage_Size,
             Null_Address => CUDA_Null_Address
          );

       type CUDA_Address is new System.Address;
       --  We're assuming for now same address size on host and device

       procedure CUDA_Allocate
         (Model           : in out CUDA_Storage_Model;
          Storage_Address : out CUDA_Address;
          Size            : Storage_Count;
          Alignment       : Storage_Count);

       procedure CUDA_Deallocate
         (Model           : in out CUDA_Storage_Model;
          Storage_Address : out CUDA_Address;
          Size            : Storage_Count;
          Alignment       : Storage_Count);

       procedure CUDA_Copy_To
         (Model  : in out CUDA_Storage_Model;
          Target : CUDA_Address;
          Source : System.Address;
          Size   : Storage_Count);

       procedure CUDA_Copy_From
         (Model   : in out CUDA_Storage_Model;
          Target  : System.Address;
          Source  : CUDA_Address;
          Size    : Storage_Count);

       function CUDA_Storage_Size
         (Pool : CUDA_Storage_Model)
          return Storage_Count return Storage_Count'Last;

       CUDA_Null_Address : constant CUDA_Address :=
          CUDA_Address (System.Null_Address);

       CUDA_Memory : CUDA_Storage_Model;

    end CUDA_Memory;