lace: Add fast pools.
This commit is contained in:
231
1-base/lace/source/lace-array_based_pool.adb
Normal file
231
1-base/lace/source/lace-array_based_pool.adb
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
with
|
||||||
|
ada.Containers.Vectors,
|
||||||
|
ada.Directories,
|
||||||
|
ada.Finalization,
|
||||||
|
ada.Streams.Stream_IO,
|
||||||
|
|
||||||
|
system.storage_Elements;
|
||||||
|
|
||||||
|
|
||||||
|
package body lace.array_based_Pool
|
||||||
|
is
|
||||||
|
type Items is array (Positive range <>) of aliased Item with Convention => C; -- Convention is to ensure contiguity.
|
||||||
|
type Views is array (Positive range <>) of View;
|
||||||
|
|
||||||
|
package View_Vectors is new ada.Containers.Vectors (Positive, View);
|
||||||
|
subtype View_Vector is View_Vectors.Vector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected Pool
|
||||||
|
is
|
||||||
|
procedure Size_is (Now : in Positive);
|
||||||
|
|
||||||
|
entry new_Item (the_Item : out View);
|
||||||
|
entry free (the_Item : in View);
|
||||||
|
|
||||||
|
function max_array_Size return Natural;
|
||||||
|
function max_heap_Size return Natural;
|
||||||
|
|
||||||
|
private
|
||||||
|
my_Items : access Items;
|
||||||
|
used_Count : Natural := 0;
|
||||||
|
|
||||||
|
array_Freed : access Views;
|
||||||
|
array_freed_Count : Natural:= 0;
|
||||||
|
|
||||||
|
heap_Freed : View_Vector;
|
||||||
|
heap_Max : Natural := 0;
|
||||||
|
end Pool;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected body Pool
|
||||||
|
is
|
||||||
|
|
||||||
|
procedure Size_is (Now : in Positive)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
my_Items := new Items (1 .. Now);
|
||||||
|
array_Freed := new Views (1 .. Now);
|
||||||
|
end Size_is;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
entry new_Item (the_Item : out View)
|
||||||
|
when my_Items /= null
|
||||||
|
is
|
||||||
|
use ada.Containers,
|
||||||
|
View_Vectors;
|
||||||
|
begin
|
||||||
|
if array_freed_Count > 0
|
||||||
|
then
|
||||||
|
-- Use a freed array item.
|
||||||
|
--
|
||||||
|
the_Item := array_Freed (array_freed_Count);
|
||||||
|
array_freed_Count := array_freed_Count - 1;
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
|
||||||
|
if used_Count < my_Items'Length
|
||||||
|
then
|
||||||
|
-- Use a fresh array item.
|
||||||
|
--
|
||||||
|
used_Count := used_Count + 1;
|
||||||
|
the_Item := my_Items (used_Count)'Access;
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
|
||||||
|
if heap_Freed.Length > 0
|
||||||
|
then
|
||||||
|
-- Use a freed heap item.
|
||||||
|
--
|
||||||
|
the_Item := heap_Freed.last_Element;
|
||||||
|
heap_Freed.delete_Last;
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
|
||||||
|
-- Use a fresh heap item.
|
||||||
|
--
|
||||||
|
the_Item := new Item;
|
||||||
|
heap_max := heap_Max + 1;
|
||||||
|
end new_Item;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
entry free (the_Item : in View)
|
||||||
|
when array_Freed /= null
|
||||||
|
is
|
||||||
|
use system.storage_Elements;
|
||||||
|
|
||||||
|
item_Address : constant integer_Address := to_Integer (the_Item.all 'Address);
|
||||||
|
first_Address : constant integer_Address := to_Integer (my_Items (my_Items'First)'Address);
|
||||||
|
last_Address : constant integer_Address := to_Integer (my_Items (my_Items'Last) 'Address);
|
||||||
|
|
||||||
|
is_an_array_Item : constant Boolean := item_Address >= first_Address
|
||||||
|
and item_Address <= last_Address;
|
||||||
|
begin
|
||||||
|
if is_an_array_Item
|
||||||
|
then
|
||||||
|
array_freed_Count := array_freed_Count + 1;
|
||||||
|
array_Freed (array_freed_Count) := the_Item;
|
||||||
|
else
|
||||||
|
heap_Freed.append (the_Item);
|
||||||
|
end if;
|
||||||
|
end free;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function max_array_Size return Natural
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
return used_Count;
|
||||||
|
end max_array_Size;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function max_heap_Size return Natural
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
return heap_Max;
|
||||||
|
end max_heap_Size;
|
||||||
|
|
||||||
|
end Pool;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function new_Item return View
|
||||||
|
is
|
||||||
|
Self : View;
|
||||||
|
begin
|
||||||
|
Pool.new_Item (Self);
|
||||||
|
define (Self.all);
|
||||||
|
|
||||||
|
return Self;
|
||||||
|
end new_Item;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
procedure free (Self : in out View)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
destroy (Self.all);
|
||||||
|
Pool.free (Self);
|
||||||
|
|
||||||
|
Self := null;
|
||||||
|
end free;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- HWM: High water mark.
|
||||||
|
|
||||||
|
|
||||||
|
actual_pool_Size : Positive;
|
||||||
|
prior_HWM : Positive;
|
||||||
|
HWM_Filename : constant String := "." & Name & "-high_water_mark";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type Closure is new ada.finalization.Controlled with null record;
|
||||||
|
|
||||||
|
overriding
|
||||||
|
procedure finalize (Self : in out Closure)
|
||||||
|
is
|
||||||
|
use ada.Streams,
|
||||||
|
ada.Streams.Stream_IO;
|
||||||
|
|
||||||
|
HWM : constant Positive := Pool.max_array_Size + Pool.max_heap_Size;
|
||||||
|
File : File_type;
|
||||||
|
S : access Root_Stream_Type;
|
||||||
|
begin
|
||||||
|
if HWM > prior_HWM -- TODO: Consider using the median of the last 5 HWM's.
|
||||||
|
then
|
||||||
|
create (File, out_File, HWM_Filename);
|
||||||
|
|
||||||
|
S := Stream (File);
|
||||||
|
String'output (S, HWM'Image);
|
||||||
|
close (File);
|
||||||
|
end if;
|
||||||
|
end finalize;
|
||||||
|
|
||||||
|
Closer : Closure with Unreferenced;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use ada.Directories;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if not Exists (HWM_Filename)
|
||||||
|
then
|
||||||
|
actual_pool_Size := initial_pool_Size;
|
||||||
|
else
|
||||||
|
declare
|
||||||
|
use ada.Streams,
|
||||||
|
ada.Streams.Stream_IO;
|
||||||
|
|
||||||
|
File : File_type;
|
||||||
|
S : access Root_Stream_Type;
|
||||||
|
begin
|
||||||
|
open (File, in_File, HWM_Filename);
|
||||||
|
|
||||||
|
S := Stream (File);
|
||||||
|
prior_HWM := Positive'Value (String'input (S));
|
||||||
|
|
||||||
|
close (File);
|
||||||
|
|
||||||
|
actual_pool_Size := prior_HWM;
|
||||||
|
end;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Pool.Size_is (actual_pool_Size);
|
||||||
|
|
||||||
|
|
||||||
|
end lace.array_based_Pool;
|
||||||
18
1-base/lace/source/lace-array_based_pool.ads
Normal file
18
1-base/lace/source/lace-array_based_pool.ads
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
generic
|
||||||
|
type Item is private;
|
||||||
|
type View is access all Item;
|
||||||
|
|
||||||
|
Name : String;
|
||||||
|
initial_pool_Size : Positive := 5_000;
|
||||||
|
|
||||||
|
with procedure define (Self : out Item) is null;
|
||||||
|
with procedure destroy (Self : in out Item) is null;
|
||||||
|
|
||||||
|
|
||||||
|
package lace.array_based_Pool
|
||||||
|
is
|
||||||
|
|
||||||
|
function new_Item return View;
|
||||||
|
procedure free (Self : in out View);
|
||||||
|
|
||||||
|
end lace.array_based_Pool;
|
||||||
61
1-base/lace/source/lace-heap_based_pool.adb
Normal file
61
1-base/lace/source/lace-heap_based_pool.adb
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package body lace.heap_based_Pool
|
||||||
|
is
|
||||||
|
|
||||||
|
type Views is array (1 .. pool_Size) of View;
|
||||||
|
|
||||||
|
|
||||||
|
protected Pool
|
||||||
|
is
|
||||||
|
entry new_Item (the_Item : out View);
|
||||||
|
entry free (the_Item : in View);
|
||||||
|
private
|
||||||
|
Available : Views;
|
||||||
|
Count : Natural := 0;
|
||||||
|
end Pool;
|
||||||
|
|
||||||
|
|
||||||
|
protected body Pool
|
||||||
|
is
|
||||||
|
entry new_Item (the_Item : out View)
|
||||||
|
when True
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
if Count = 0
|
||||||
|
then
|
||||||
|
the_Item := new Item;
|
||||||
|
else
|
||||||
|
the_Item := Available (Count);
|
||||||
|
Count := Count - 1;
|
||||||
|
end if;
|
||||||
|
end new_Item;
|
||||||
|
|
||||||
|
|
||||||
|
entry free (the_Item : in View)
|
||||||
|
when True
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Count := Count + 1;
|
||||||
|
Available (Count) := the_Item;
|
||||||
|
end free;
|
||||||
|
end Pool;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function new_Item return View
|
||||||
|
is
|
||||||
|
Self : View;
|
||||||
|
begin
|
||||||
|
Pool.new_Item (Self);
|
||||||
|
return Self;
|
||||||
|
end new_Item;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
procedure free (Self : in out View)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
Pool.free (Self);
|
||||||
|
Self := null;
|
||||||
|
end free;
|
||||||
|
|
||||||
|
end lace.heap_based_Pool;
|
||||||
13
1-base/lace/source/lace-heap_based_pool.ads
Normal file
13
1-base/lace/source/lace-heap_based_pool.ads
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
generic
|
||||||
|
type Item is private;
|
||||||
|
type View is access all Item;
|
||||||
|
|
||||||
|
pool_Size : Positive := 5_000;
|
||||||
|
|
||||||
|
package lace.heap_based_Pool
|
||||||
|
is
|
||||||
|
|
||||||
|
function new_Item return View;
|
||||||
|
procedure free (Self : in out View);
|
||||||
|
|
||||||
|
end lace.heap_based_Pool;
|
||||||
Reference in New Issue
Block a user