diff --git a/src/shared/mempool.pas b/src/shared/mempool.pas
index 1604055c028f6620f115998343a90966a458eb5d..ff1e65692a976ee0c7f1b73d71cbffb4e05fced4 100644 (file)
--- a/src/shared/mempool.pas
+++ b/src/shared/mempool.pas
type
PoolMark = Integer;
+ PPoolMarkRelease = ^TPoolMarkRelease;
TPoolMarkRelease = record
private
mMemory: Pointer;
// get pointer for the given mark
// WARNING! pointer can become invalid after next call to `alloc()`!
function getPtr (amark: PoolMark): Pointer; inline;
+ function curPtr (): Pointer; inline;
+ end;
+
+
+type
+ generic PoolIter<T> = record
+ public
+ type Ptr = ^T;
+ type MyType = specialize PoolIter<T>;
+
+ private
+ mPool: PPoolMarkRelease;
+ mMark: PoolMark;
+ mCount: Integer;
+ mCurrent: Integer;
+ mFinished: Boolean;
+
+ public
+ constructor Create (var apool: TPoolMarkRelease); // idiotic FPC doesn't support arg-less ctors for rectord
+ procedure finishIt (); inline; // sets count
+
+ procedure rewind (); inline;
+ function length (): Integer; inline;
+ procedure release (); inline; // reset pool
+
+ function moveNext (): Boolean; inline;
+ function getCurrent (): Ptr; inline;
+ function getEnumerator (): MyType; inline;
+
+ function first (): Ptr; inline;
+
+ public
+ property current: Ptr read getCurrent;
end;
end;
+function TPoolMarkRelease.curPtr (): Pointer; inline;
+begin
+ result := Pointer(PAnsiChar(mMemory)+mUsed);
+end;
+
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor PoolIter.Create (var apool: TPoolMarkRelease);
+begin
+ mPool := @apool;
+ mMark := mPool^.mark();
+ mCount := 0;
+ mCurrent := -1;
+ mFinished := false;
+end;
+
+
+procedure PoolIter.finishIt (); inline; // sets count
+begin
+ if (mFinished) then raise Exception.Create('double fatality');
+ if (mPool = nil) then raise Exception.Create('void fatality');
+ mFinished := true;
+ mCount := Integer(PtrUInt(mPool^.curPtr)-PtrUInt(mPool^.getPtr(mMark))) div Integer(sizeof(T));
+ if (mCount < 0) then raise Exception.Create('wutafu?');
+end;
+
+
+procedure PoolIter.rewind (); inline;
+begin
+ if (mPool = nil) then raise Exception.Create('void rewind');
+ mCurrent := -1;
+end;
+
+
+function PoolIter.length (): Integer; inline;
+begin
+ //if (mCurrent+1 >= 0) and (mCurrent+1 < mCount) then result := mCount-(mCurrent+1) else result := 0;
+ result := mCount;
+end;
+
+
+procedure PoolIter.release (); inline; // reset pool
+begin
+ if (mPool = nil) then raise Exception.Create('double release');
+ mPool^.release(mMark);
+ mPool := nil;
+ mCount := 0;
+ mCurrent := -1;
+ mFinished := false;
+end;
+
+
+function PoolIter.moveNext (): Boolean; inline;
+begin
+ if (mPool = nil) then raise Exception.Create('void moveNext()');
+ if (not mFinished) then raise Exception.Create('moveNext() on unfinished');
+ Inc(mCurrent);
+ result := (mCurrent < mCount);
+end;
+
+
+function PoolIter.getCurrent (): Ptr; inline;
+begin
+ if (mPool = nil) then raise Exception.Create('getCurrent() on nothing');
+ if (mCurrent < 0) or (mCurrent >= mCount) then raise Exception.Create('getCurrent() range error');
+ result := Ptr(mPool^.getPtr(mMark+mCurrent*Integer(sizeof(T))));
+end;
+
+
+function PoolIter.getEnumerator (): PoolIter; inline;
+begin
+ result := self;
+end;
+
+
+function PoolIter.first (): Ptr; inline;
+begin
+ if (mPool = nil) then raise Exception.Create('void moveNext()');
+ if (not mFinished) then raise Exception.Create('moveNext() on unfinished');
+ result := Ptr(mPool^.getPtr(mMark));
+end;
+
+
// ////////////////////////////////////////////////////////////////////////// //
{$IFDEF USE_MEMPOOL}
uses