{$MODE OBJFPC}
unit dstaticpool;

interface

type
// TItem must implement interface:
//   field TItem.FNext: PItem
generic TStaticPool<TItem> = object
private type
  PItem = ^TItem;
private
  FItems: PItem;
  FCount: LongInt;
  FIndex: LongInt;
  FFirstFree: PItem;
public
  procedure Init(var StaticArray: array of TItem); inline;
  procedure Done; inline;
  function AllocItem: PItem;
  procedure FreeItem(Item: PItem); inline;
end;

implementation

procedure TStaticPool.Init(var StaticArray: array of TItem);
begin
  FItems := @StaticArray[0];
  FCount := Length(StaticArray);
  FIndex := 0;
  FFirstFree := nil;
end;

procedure TStaticPool.Done;
begin
end;

function TStaticPool.AllocItem: PItem;
begin
  if FFirstFree <> nil then begin
    Result := FFirstFree;
    FFirstFree := FFirstFree^.FNext;
    Exit;
  end;
  if FIndex < FCount then begin
    Result := @FItems[FIndex];
    Inc(FIndex);
    Exit;
  end;
  Result := nil;
end;

procedure TStaticPool.FreeItem(Item: PItem);
begin
  Item^.FNext := FFirstFree;
  FFirstFree := Item;
end;

end.
