X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fshared%2Fmempool.pas;h=a521626e051439be0cb5bc75417bbdaa036b17fd;hb=987c4a835a103345b59937e8e1be8524a6228712;hp=1604055c028f6620f115998343a90966a458eb5d;hpb=c1a1cdafd1d0e3f877a20994b57fdb389373d1d4;p=d2df-sdl.git diff --git a/src/shared/mempool.pas b/src/shared/mempool.pas index 1604055..a521626 100644 --- a/src/shared/mempool.pas +++ b/src/shared/mempool.pas @@ -2,8 +2,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -63,6 +62,7 @@ type type PoolMark = Integer; + PPoolMarkRelease = ^TPoolMarkRelease; TPoolMarkRelease = record private mMemory: Pointer; @@ -90,6 +90,39 @@ type // 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 = record + public + type Ptr = ^T; + type MyType = specialize PoolIter; + + 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; @@ -193,6 +226,90 @@ begin 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