固定長メモリマネージャ2

というわけでModern C++ Design*1を引っ張り出してきて、起きた頭で書き直し。

type
	TFixedMemoryManager = object
	private
		Memory: Pointer;
		UnitSize: Cardinal;
		First: Pointer;
		Last: Pointer;
	public
		constructor Initialize(AUnitSize: Cardinal);
		destructor Finalize;
		function Allocate: Pointer;
		procedure Free(AUnit: Pointer);
	end;
{ TFixedMemoryManager }

function TFixedMemoryManager.Allocate: Pointer;
var
	NewCommitSize: Integer;
	Next, I: Pointer;
begin
	if First = Last then
	begin
		NewCommitSize := UnitSize * 1024;

		if VirtualAlloc(Last, NewCommitSize, MEM_COMMIT, PAGE_READWRITE) = nil then
			OutOfMemoryError;

		Result := First;

		Inc(Cardinal(Last), NewCommitSize);
		Inc(Cardinal(First), UnitSize);

		I := First;
		while Cardinal(I) < Cardinal(Last) do
		begin
			Next := Pointer(Cardinal(I) + UnitSize);
			PPointer(I)^ := Next;
			I := Next;
		end;
	end
	else
	begin
		Result := First;
		First := PPointer(Result)^;
	end;
end;

destructor TFixedMemoryManager.Finalize;
var
	Commited: Cardinal;
begin
	Commited := Cardinal(Last) - Cardinal(Memory);
	if Commited <> 0 then
		VirtualFree(Memory, Commited, MEM_DECOMMIT);
	if Memory <> nil then
	begin
{$IFOPT C+}
		if not VirtualFree(Memory, 0, MEM_RELEASE) then RaiseLastOSError;
{$ELSE}
		VirtualFree(Memory, 0, MEM_RELEASE);
{$ENDIF}
	end;
end;

procedure TFixedMemoryManager.Free(AUnit: Pointer);
begin
	PPointer(AUnit)^ := First;
	First := AUnit;
end;

constructor TFixedMemoryManager.Initialize(AUnitSize: Cardinal);
const
	MaxLogicalLimitation = 1024 * 1024 * 1024; {1GB!}
var
	LogicalLimitation: Cardinal;
begin
	UnitSize := AUnitSize;
	if AUnitSize < SizeOf(Pointer) then
		UnitSize := SizeOf(Pointer);

	First := nil;
	Last := nil;

	LogicalLimitation := MaxLogicalLimitation;
	repeat
		Memory := VirtualAlloc(nil, LogicalLimitation, MEM_RESERVE, PAGE_READWRITE);
		if Memory <> nil then Break;
		LogicalLimitation := LogicalLimitation div 2;
		if LogicalLimitation < AUnitSize then
			OutOfMemoryError;
	until False;

	First := Memory;
	Last := Memory;
end;

速い!圧倒的に速い!
ヒープ関数や上の実装の1/10以上速く動きます。

*1:この本初めて役に立ったかも…