X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fshared%2Fmempool.pas;h=ae67f034aa60363ec362b8b04b4a6ff2f4bec870;hb=52046a296d5acd6588c2dde5918cdb6cbd26fc52;hp=1604055c028f6620f115998343a90966a458eb5d;hpb=0cf1438ff1766dc311fbebc45f6171d64f757cd4;p=d2df-sdl.git diff --git a/src/shared/mempool.pas b/src/shared/mempool.pas index 1604055..ae67f03 100644 --- a/src/shared/mempool.pas +++ b/src/shared/mempool.pas @@ -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 + mMark: PoolMark; + mCount: Integer; + mCurrent: Integer; + mFinished: Boolean; + + public + constructor Create (dummy: Boolean); // idiotic FPC doesn't support arg-less ctors for rectord + procedure startIt (); inline; // automatically called by ctor; does NO checks! + 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,94 @@ begin end; +function TPoolMarkRelease.curPtr (): Pointer; inline; +begin + result := Pointer(PAnsiChar(mMemory)+mUsed); +end; + + + +// ////////////////////////////////////////////////////////////////////////// // +constructor PoolIter.Create (dummy: Boolean); +begin + startIt(); +end; + + +procedure PoolIter.startIt (); inline; // automatically called by ctor; does NO checks! +begin + mMark := framePool.mark(); + mCount := 0; + mCurrent := -1; + mFinished := false; +end; + + +procedure PoolIter.finishIt (); inline; // sets count +begin + if (mFinished) then raise Exception.Create('double fatality'); + if (mMark = -1) then raise Exception.Create('void fatality'); + mFinished := true; + mCount := Integer(PtrUInt(framePool.curPtr)-PtrUInt(framePool.getPtr(mMark))) div Integer(sizeof(T)); + if (mCount < 0) then raise Exception.Create('wutafu?'); +end; + + +procedure PoolIter.rewind (); inline; +begin + if (mMark = -1) 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 (mMark = -1) then raise Exception.Create('double release'); + framePool.release(mMark); + mMark := -1; + mCount := 0; + mCurrent := -1; + mFinished := false; +end; + + +function PoolIter.moveNext (): Boolean; inline; +begin + if (mMark = -1) 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 (mCurrent < 0) or (mCurrent >= mCount) then raise Exception.Create('getCurrent() range error'); + result := Ptr(framePool.getPtr(mMark+mCurrent*Integer(sizeof(T)))); +end; + + +function PoolIter.getEnumerator (): PoolIter; inline; +begin + result := self; +end; + + +function PoolIter.first (): Ptr; inline; +begin + if (mMark = -1) then raise Exception.Create('void moveNext()'); + if (not mFinished) then raise Exception.Create('moveNext() on unfinished'); + result := Ptr(framePool.getPtr(mMark)); +end; + + // ////////////////////////////////////////////////////////////////////////// // {$IFDEF USE_MEMPOOL} uses