home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / s-poosiz.adb < prev    next >
Text File  |  2000-07-19  |  12KB  |  357 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUN-TIME COMPONENTS                         --
  4. --                                                                          --
  5. --                     S Y S T E M . P O O L _ S I Z E                      --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.13 $                             --
  10. --                                                                          --
  11. --          Copyright (C) 1992-1998 Free Software Foundation, Inc.          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT was originally developed  by the GNAT team at  New York University. --
  32. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  33. --                                                                          --
  34. ------------------------------------------------------------------------------
  35.  
  36. with System.Storage_Elements;
  37. with System.Address_To_Access_Conversions;
  38.  
  39. package body System.Pool_Size is
  40.  
  41.    package SSE renames System.Storage_Elements;
  42.    use type SSE.Storage_Offset;
  43.  
  44.    package SC is new Address_To_Access_Conversions (SSE.Storage_Count);
  45.  
  46.    SC_Size : constant
  47.      :=  SSE.Storage_Count'Object_Size / System.Storage_Unit;
  48.  
  49.    package Variable_Size_Management is
  50.  
  51.       --  Embedded pool that manages allocation of variable-size data.
  52.  
  53.       --  This pool is used as soon as the Elmt_sizS of the pool object is 0.
  54.  
  55.       --  Allocation is done on the first chunk long enough for the request.
  56.       --  Deallocation just puts the freed chunk at the beginning of the list.
  57.  
  58.       procedure Initialize  (Pool : in out Stack_Bounded_Pool);
  59.       procedure Allocate
  60.         (Pool         : in out Stack_Bounded_Pool;
  61.          Address      : out System.Address;
  62.          Storage_Size : SSE.Storage_Count;
  63.          Alignment    : SSE.Storage_Count);
  64.  
  65.       procedure Deallocate
  66.         (Pool         : in out Stack_Bounded_Pool;
  67.          Address      : System.Address;
  68.          Storage_Size : SSE.Storage_Count;
  69.          Alignment    : SSE.Storage_Count);
  70.    end Variable_Size_Management;
  71.  
  72.    package Vsize renames Variable_Size_Management;
  73.  
  74.    ------------------
  75.    -- Storage_Size --
  76.    ------------------
  77.  
  78.    function  Storage_Size
  79.      (Pool : Stack_Bounded_Pool)
  80.       return SSE.Storage_Count
  81.    is
  82.    begin
  83.       return Pool.Pool_Size;
  84.    end Storage_Size;
  85.  
  86.    --------------
  87.    -- Allocate --
  88.    --------------
  89.  
  90.    procedure Allocate
  91.      (Pool         : in out Stack_Bounded_Pool;
  92.       Address      : out System.Address;
  93.       Storage_Size : SSE.Storage_Count;
  94.       Alignment    : SSE.Storage_Count)
  95.    is
  96.    begin
  97.       if Pool.Elmt_Size = 0 then
  98.          Vsize.Allocate (Pool, Address, Storage_Size, Alignment);
  99.  
  100.       elsif Pool.First_Free /= 0 then
  101.          Address := Pool.The_Pool (Pool.First_Free)'Address;
  102.          Pool.First_Free := SC.To_Pointer (Address).all;
  103.  
  104.       elsif
  105.         Pool.First_Empty <= (Pool.Pool_Size - Pool.Aligned_Elmt_Size + 1)
  106.       then
  107.          Address := Pool.The_Pool (Pool.First_Empty)'Address;
  108.          Pool.First_Empty := Pool.First_Empty + Pool.Aligned_Elmt_Size;
  109.  
  110.       else
  111.          raise Storage_Error;
  112.       end if;
  113.    end Allocate;
  114.  
  115.    ----------------
  116.    -- Deallocate --
  117.    ----------------
  118.  
  119.    procedure Deallocate
  120.      (Pool         : in out Stack_Bounded_Pool;
  121.       Address      : System.Address;
  122.       Storage_Size : SSE.Storage_Count;
  123.       Alignment    : SSE.Storage_Count)
  124.    is
  125.    begin
  126.       if Pool.Elmt_Size = 0 then
  127.          Vsize.Deallocate (Pool, Address, Storage_Size, Alignment);
  128.  
  129.       else
  130.          SC.To_Pointer (Address).all := Pool.First_Free;
  131.          Pool.First_Free := Address - Pool.The_Pool'Address + 1;
  132.       end if;
  133.    end Deallocate;
  134.  
  135.    ----------------
  136.    -- Initialize --
  137.    ----------------
  138.  
  139.    procedure Initialize  (Pool : in out Stack_Bounded_Pool) is
  140.       Align : constant SSE.Storage_Count :=
  141.         SSE.Storage_Count'Max (SSE.Storage_Count'Alignment, Pool.Alignment);
  142.  
  143.    begin
  144.       if Pool.Elmt_Size = 0 then
  145.          Vsize.Initialize (Pool);
  146.  
  147.       else
  148.          Pool.First_Free := 0;
  149.          Pool.First_Empty := 1;
  150.  
  151.          --  Compute the size to allocate given the size of the element and
  152.          --  the possible Alignment clause
  153.  
  154.          Pool.Aligned_Elmt_Size :=
  155.            SSE.Storage_Count'Max (SC_Size,
  156.              ((Pool.Elmt_Size + Align - 1) / Align) * Align);
  157.       end if;
  158.    end Initialize;
  159.  
  160.    ------------------------------
  161.    -- Variable_Size_Management --
  162.    ------------------------------
  163.  
  164.    package body Variable_Size_Management is
  165.  
  166.       Minimum_Size : constant := 2 * SC_Size;
  167.  
  168.       procedure Set_Size
  169.         (Pool        : Stack_Bounded_Pool;
  170.          Chunk, Size : SSE.Storage_Count);
  171.       --  Update the field 'size' of a chunk of available storage
  172.  
  173.       procedure Set_Next
  174.         (Pool        : Stack_Bounded_Pool;
  175.          Chunk, Next : SSE.Storage_Count);
  176.       --  Update the field 'next' of a chunk of available storage
  177.  
  178.       function Size
  179.         (Pool  : Stack_Bounded_Pool;
  180.          Chunk : SSE.Storage_Count)
  181.          return SSE.Storage_Count;
  182.       --  Fetch the field 'size' of a chunk of available storage
  183.  
  184.       function Next
  185.         (Pool  : Stack_Bounded_Pool;
  186.          Chunk : SSE.Storage_Count)
  187.          return  SSE.Storage_Count;
  188.       --  Fetch the field 'next' of a chunk of available storage
  189.  
  190.       function Chunk_Of
  191.         (Pool : Stack_Bounded_Pool;
  192.          Addr : System.Address)
  193.          return SSE.Storage_Count;
  194.       --  Give the chunk number in the pool from its Address
  195.  
  196.       --------------
  197.       -- Set_Size --
  198.       --------------
  199.  
  200.       procedure Set_Size
  201.         (Pool        : Stack_Bounded_Pool;
  202.          Chunk, Size : SSE.Storage_Count)
  203.       is
  204.       begin
  205.          SC.To_Pointer (Pool.The_Pool (Chunk)'Address).all := Size;
  206.       end Set_Size;
  207.  
  208.       --------------
  209.       -- Set_Next --
  210.       --------------
  211.  
  212.       procedure Set_Next
  213.         (Pool        : Stack_Bounded_Pool;
  214.          Chunk, Next : SSE.Storage_Count)
  215.       is
  216.       begin
  217.          SC.To_Pointer (Pool.The_Pool (Chunk + SC_Size)'Address).all := Next;
  218.       end Set_Next;
  219.  
  220.       ----------
  221.       -- Size --
  222.       ----------
  223.  
  224.       function Size
  225.         (Pool  : Stack_Bounded_Pool;
  226.          Chunk : SSE.Storage_Count)
  227.          return  SSE.Storage_Count
  228.       is
  229.       begin
  230.          return  SC.To_Pointer (Pool.The_Pool (Chunk)'Address).all;
  231.       end Size;
  232.  
  233.       ----------
  234.       -- Next --
  235.       ----------
  236.  
  237.       function Next
  238.         (Pool  : Stack_Bounded_Pool;
  239.          Chunk : SSE.Storage_Count)
  240.          return  SSE.Storage_Count
  241.       is
  242.       begin
  243.          return SC.To_Pointer (Pool.The_Pool (Chunk + SC_Size)'Address).all;
  244.       end Next;
  245.  
  246.       --------------
  247.       -- Chunk_Of --
  248.       --------------
  249.  
  250.       function Chunk_Of
  251.         (Pool : Stack_Bounded_Pool;
  252.          Addr : System.Address)
  253.          return SSE.Storage_Count
  254.       is
  255.       begin
  256.          return 1 + abs (Addr - Pool.The_Pool (1)'Address);
  257.       end Chunk_Of;
  258.  
  259.       --------------
  260.       -- Allocate --
  261.       --------------
  262.  
  263.       procedure Allocate
  264.         (Pool         : in out Stack_Bounded_Pool;
  265.          Address      : out System.Address;
  266.          Storage_Size : SSE.Storage_Count;
  267.          Alignment    : SSE.Storage_Count)
  268.       is
  269.          Chunk      : SSE.Storage_Count;
  270.          New_Chunk  : SSE.Storage_Count;
  271.          Prev_Chunk : SSE.Storage_Count;
  272.          Our_Align  : constant SSE.Storage_Count :=
  273.                         SSE.Storage_Count'Max (SSE.Storage_Count'Alignment,
  274.                                                Alignment);
  275.          Align_Size : constant SSE.Storage_Count :=
  276.                         SSE.Storage_Count'Max (
  277.                           Minimum_Size,
  278.                           ((Storage_Size + Our_Align - 1) / Our_Align) *
  279.                                                                   Our_Align);
  280.  
  281.       begin
  282.          --   Look for the first big enough chunk
  283.  
  284.          Prev_Chunk := Pool.First_Free;
  285.          Chunk := Next (Pool, Prev_Chunk);
  286.          while Size (Pool, Chunk) < Align_Size loop
  287.             if Next (Pool, Chunk) = 0 then
  288.                raise Storage_Error;
  289.             else
  290.                Prev_Chunk := Chunk;
  291.                Chunk := Next (Pool, Chunk);
  292.             end if;
  293.          end loop;
  294.  
  295.          --  When the chunk is bigger than what is needed, take appropraite
  296.          --  amount and build a new shrinked chunk with the remainder.
  297.  
  298.          if Size (Pool, Chunk) - Align_Size  > Minimum_Size then
  299.             New_Chunk := Chunk + Align_Size;
  300.             Set_Size (Pool, New_Chunk, Size (Pool, Chunk) - Align_Size);
  301.             Set_Next (Pool, New_Chunk, Next (Pool, Chunk));
  302.             Set_Next (Pool, Prev_Chunk, New_Chunk);
  303.  
  304.          --  If the chunk is the right size, just delete it from the chain
  305.  
  306.          else
  307.             Set_Next (Pool, Prev_Chunk, Next (Pool, Chunk));
  308.          end if;
  309.  
  310.          Address := Pool.The_Pool (Chunk)'Address;
  311.       end Allocate;
  312.  
  313.       ----------------
  314.       -- Deallocate --
  315.       ----------------
  316.  
  317.       procedure Deallocate
  318.         (Pool         : in out Stack_Bounded_Pool;
  319.          Address      : System.Address;
  320.          Storage_Size : SSE.Storage_Count;
  321.          Alignment    : SSE.Storage_Count)
  322.       is
  323.          Align_Size : constant SSE.Storage_Count :=
  324.                         ((Storage_Size + Alignment - 1) / Alignment) *
  325.                                                                  Alignment;
  326.          Chunk : SSE.Storage_Count := Chunk_Of (Pool, Address);
  327.  
  328.       begin
  329.          --  Attach the freed chunk to the chain
  330.  
  331.          Set_Size (Pool, Chunk,
  332.                          SSE.Storage_Count'Max (Align_Size, Minimum_Size));
  333.          Set_Next (Pool, Chunk, Next (Pool, Pool.First_Free));
  334.          Set_Next (Pool, Pool.First_Free,  Chunk);
  335.  
  336.       end Deallocate;
  337.  
  338.       ----------------
  339.       -- Initialize --
  340.       ----------------
  341.  
  342.       procedure Initialize  (Pool : in out Stack_Bounded_Pool) is
  343.       begin
  344.          Pool.First_Free := 1;
  345.  
  346.          if Pool.Pool_Size > Minimum_Size then
  347.             Set_Next (Pool, Pool.First_Free, Pool.First_Free + Minimum_Size);
  348.             Set_Size (Pool, Pool.First_Free, 0);
  349.             Set_Size (Pool, Pool.First_Free + Minimum_Size,
  350.                                               Pool.Pool_Size - Minimum_Size);
  351.             Set_Next (Pool, Pool.First_Free + Minimum_Size, 0);
  352.          end if;
  353.       end Initialize;
  354.  
  355.    end  Variable_Size_Management;
  356. end System.Pool_Size;
  357.