2010-06-02 10:30 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/src/vm/garbage.c
+ added new PRG function HB_GCSETAUTO( [<nNewVal>] ) -> <nPrevVal>
which allows to set the frequency of automatic GC activation.
<nNewVal> is number of GC items (in thousands). If total number
of new GC items allocated from last GC pass exceed this value
then GC is automatically activated. Setting 0 disable automatic
GC activation. Automatic GC activation is necessary for programs
which allocates big number of complex items with cyclic references
without entering any idle state which can activate GC. In such
case users have to add to their code call to hb_gcAll() function.
In xHarbour they used sometimes background task for this job
but it's inefficient workaround for the problem due to reduced
performance.
This code is still experimental code enabled by HB_GC_AUTO Harbour
compile time macro.
* harbour/src/debug/dbgentry.c
! fixed potential memory leak in unused code for GLOBAL [EXTERN]
variables
! cleaned a little bit code for line numbers with good break points
This commit is contained in:
@@ -17,6 +17,28 @@
|
||||
past entries belonging to author(s): Viktor Szakats.
|
||||
*/
|
||||
|
||||
2010-06-02 10:30 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/src/vm/garbage.c
|
||||
+ added new PRG function HB_GCSETAUTO( [<nNewVal>] ) -> <nPrevVal>
|
||||
which allows to set the frequency of automatic GC activation.
|
||||
<nNewVal> is number of GC items (in thousands). If total number
|
||||
of new GC items allocated from last GC pass exceed this value
|
||||
then GC is automatically activated. Setting 0 disable automatic
|
||||
GC activation. Automatic GC activation is necessary for programs
|
||||
which allocates big number of complex items with cyclic references
|
||||
without entering any idle state which can activate GC. In such
|
||||
case users have to add to their code call to hb_gcAll() function.
|
||||
In xHarbour they used sometimes background task for this job
|
||||
but it's inefficient workaround for the problem due to reduced
|
||||
performance.
|
||||
This code is still experimental code enabled by HB_GC_AUTO Harbour
|
||||
compile time macro.
|
||||
|
||||
* harbour/src/debug/dbgentry.c
|
||||
! fixed potential memory leak in unused code for GLOBAL [EXTERN]
|
||||
variables
|
||||
! cleaned a little bit code for line numbers with good break points
|
||||
|
||||
2010-06-02 00:41 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com)
|
||||
* contrib/gtwvg/tests/demowvg.prg
|
||||
* contrib/gtwvg/tests/wvgcuigdialog.prg
|
||||
|
||||
@@ -702,21 +702,26 @@ static void hb_dbgAddStopLines( HB_DEBUGINFO * info, PHB_ITEM pItem )
|
||||
int nOrigLen = hb_arrayGetCLen( pLines, 3 );
|
||||
int nNewLen = hb_arrayGetCLen( pEntry, 3 );
|
||||
int nMin = HB_MIN( nNewMin, nOrigMin );
|
||||
int nMax = HB_MAX( nNewMin + nNewLen * 8, nOrigMin + nOrigLen * 8 );
|
||||
int nMax = HB_MAX( nNewMin + ( nNewLen << 3 ) - 1,
|
||||
nOrigMin + ( nOrigLen << 3 ) - 1 );
|
||||
const char * pOrigBuffer = hb_arrayGetCPtr( pLines, 3 );
|
||||
const char * pNewBuffer = hb_arrayGetCPtr( pEntry, 3 );
|
||||
int nLen = ( nMax + 1 - nMin + 7 ) / 8 + 1;
|
||||
int nLen = ( ( nMax - nMin ) >> 3 ) + 1;
|
||||
int k;
|
||||
char * pBuffer = ( char * ) hb_xgrab( nLen );
|
||||
char * pBuffer = ( char * ) hb_xgrab( nLen + 1 );
|
||||
|
||||
hb_xmemset( pBuffer, 0, nLen );
|
||||
|
||||
memmove( &( pBuffer[ ( nNewMin - nMin ) / 8 ] ), pNewBuffer, nNewLen );
|
||||
/* the bitfields with line numbers should use
|
||||
* 8bit alignment so it's safe to use byte copy
|
||||
*/
|
||||
memmove( &pBuffer[ ( nNewMin - nMin ) >> 3 ], pNewBuffer, nNewLen );
|
||||
nOrigMin = ( nOrigMin - nMin ) >> 3;
|
||||
for( k = 0; k < nOrigLen; k++ )
|
||||
pBuffer[ nOrigMin / 8 + k - nMin / 8 ] |= pOrigBuffer[ k ];
|
||||
pBuffer[ nOrigMin + k ] |= pOrigBuffer[ k ];
|
||||
|
||||
hb_arraySetNL( pLines, 2, nMin );
|
||||
if( !hb_arraySetCLPtr( pLines, 3, pBuffer, nLen - 1 ) )
|
||||
if( !hb_arraySetCLPtr( pLines, 3, pBuffer, nLen ) )
|
||||
hb_xfree( pBuffer );
|
||||
bFound = HB_TRUE;
|
||||
break;
|
||||
@@ -1351,10 +1356,10 @@ HB_BOOL hb_dbgIsValidStopLine( void * handle, const char * szModule, int nLine )
|
||||
int nMin = hb_arrayGetNL( pEntry, 2 );
|
||||
int nOfs = nLine - nMin;
|
||||
|
||||
if( nLine < nMin || ( HB_SIZE )( nOfs / 8 ) > hb_arrayGetCLen( pEntry, 3 ) )
|
||||
if( nOfs < 0 || ( HB_SIZE ) ( nOfs >> 3 ) >= hb_arrayGetCLen( pEntry, 3 ) )
|
||||
return HB_FALSE;
|
||||
|
||||
return ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs / 8 ] & ( 1 << ( nOfs % 8 ) ) ) != 0;
|
||||
return ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs >> 3 ] & ( 1 << ( nOfs & 0x07 ) ) ) != 0;
|
||||
}
|
||||
}
|
||||
return HB_FALSE;
|
||||
@@ -1387,6 +1392,14 @@ static void hb_dbgQuit( HB_DEBUGINFO * info )
|
||||
{
|
||||
hb_xfree( module->aStatics );
|
||||
}
|
||||
if( module->nGlobals )
|
||||
{
|
||||
hb_xfree( module->aGlobals );
|
||||
}
|
||||
if( module->nExternGlobals )
|
||||
{
|
||||
hb_xfree( module->aExternGlobals );
|
||||
}
|
||||
if( module->szModule )
|
||||
{
|
||||
hb_xfree( module->szModule );
|
||||
|
||||
@@ -131,14 +131,15 @@ typedef struct HB_GARBAGE_
|
||||
#define HB_GC_DELETELST 4 /* item will be deleted during finalization */
|
||||
|
||||
#ifdef HB_GC_AUTO
|
||||
#define HB_GC_AUTO_CHECK 100000
|
||||
#define HB_GC_AUTO_MAX ( ( HB_PTRUINT ) ( -1 ) );
|
||||
#define HB_GC_AUTO_MAX ( ( HB_PTRUINT ) ( -1 ) )
|
||||
/* number of allocated memory blocks */
|
||||
static HB_PTRUINT s_ulBlocks = 0;
|
||||
/* number of allocated memory blocks after last GC activation */
|
||||
static HB_PTRUINT s_ulBlocksMarked = 0;
|
||||
/* number of memory blocks between automatic GC activation */
|
||||
static HB_PTRUINT s_ulBlocksAuto = 0;
|
||||
/* number of allocated memory blocks which should force next GC activation */
|
||||
static HB_PTRUINT s_ulBlocksCheck = HB_GC_AUTO_CHECK;
|
||||
static HB_PTRUINT s_ulBlocksCheck = 0;
|
||||
|
||||
# define HB_GC_AUTO_INC ++s_ulBlocks;
|
||||
# define HB_GC_AUTO_DEC --s_ulBlocks;
|
||||
@@ -200,28 +201,14 @@ void * hb_gcAllocate( HB_SIZE ulSize, const HB_GC_FUNCS * pFuncs )
|
||||
HB_GARBAGE_PTR pAlloc;
|
||||
|
||||
pAlloc = HB_GARBAGE_NEW( ulSize );
|
||||
if( pAlloc )
|
||||
{
|
||||
pAlloc->pFuncs = pFuncs;
|
||||
pAlloc->locked = 1;
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
HB_GC_LOCK
|
||||
#ifdef HB_GC_AUTO
|
||||
if( s_ulBlocks > s_ulBlocksCheck )
|
||||
{
|
||||
HB_GC_UNLOCK
|
||||
hb_gcCollectAll( HB_TRUE );
|
||||
HB_GC_LOCK
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
}
|
||||
#endif
|
||||
hb_gcLink( &s_pLockedBlock, pAlloc );
|
||||
HB_GC_UNLOCK
|
||||
pAlloc->pFuncs = pFuncs;
|
||||
pAlloc->locked = 1;
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
HB_GC_LOCK
|
||||
hb_gcLink( &s_pLockedBlock, pAlloc );
|
||||
HB_GC_UNLOCK
|
||||
|
||||
return HB_BLOCK_PTR( pAlloc ); /* hide the internal data */
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
return HB_BLOCK_PTR( pAlloc ); /* hide the internal data */
|
||||
}
|
||||
|
||||
/* allocates a memory block */
|
||||
@@ -230,30 +217,25 @@ void * hb_gcAllocRaw( HB_SIZE ulSize, const HB_GC_FUNCS * pFuncs )
|
||||
HB_GARBAGE_PTR pAlloc;
|
||||
|
||||
pAlloc = HB_GARBAGE_NEW( ulSize );
|
||||
if( pAlloc )
|
||||
{
|
||||
pAlloc->pFuncs = pFuncs;
|
||||
pAlloc->locked = 0;
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
pAlloc->pFuncs = pFuncs;
|
||||
pAlloc->locked = 0;
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
|
||||
HB_GC_LOCK
|
||||
HB_GC_LOCK
|
||||
#ifdef HB_GC_AUTO
|
||||
if( s_ulBlocks > s_ulBlocksCheck )
|
||||
{
|
||||
HB_GC_UNLOCK
|
||||
hb_gcCollectAll( HB_TRUE );
|
||||
HB_GC_LOCK
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
}
|
||||
HB_GC_AUTO_INC
|
||||
#endif
|
||||
hb_gcLink( &s_pCurrBlock, pAlloc );
|
||||
if( s_ulBlocks > s_ulBlocksCheck )
|
||||
{
|
||||
HB_GC_UNLOCK
|
||||
|
||||
return HB_BLOCK_PTR( pAlloc ); /* hide the internal data */
|
||||
hb_gcCollectAll( HB_TRUE );
|
||||
HB_GC_LOCK
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
HB_GC_AUTO_INC
|
||||
#endif
|
||||
hb_gcLink( &s_pCurrBlock, pAlloc );
|
||||
HB_GC_UNLOCK
|
||||
|
||||
return HB_BLOCK_PTR( pAlloc ); /* hide the internal data */
|
||||
}
|
||||
|
||||
/* release a memory block allocated with hb_gcAlloc*() */
|
||||
@@ -399,30 +381,23 @@ static const HB_GC_FUNCS s_gcGripFuncs =
|
||||
|
||||
HB_ITEM_PTR hb_gcGripGet( HB_ITEM_PTR pOrigin )
|
||||
{
|
||||
HB_GARBAGE_PTR pAlloc;
|
||||
HB_GARBAGE_PTR pAlloc = HB_GARBAGE_NEW( sizeof( HB_ITEM ) );
|
||||
HB_ITEM_PTR pItem = ( HB_ITEM_PTR ) HB_BLOCK_PTR( pAlloc );
|
||||
|
||||
pAlloc = HB_GARBAGE_NEW( sizeof( HB_ITEM ) );
|
||||
if( pAlloc )
|
||||
{
|
||||
HB_ITEM_PTR pItem = ( HB_ITEM_PTR ) HB_BLOCK_PTR( pAlloc );
|
||||
pAlloc->pFuncs = &s_gcGripFuncs;
|
||||
pAlloc->locked = 1;
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
|
||||
pAlloc->pFuncs = &s_gcGripFuncs;
|
||||
pAlloc->locked = 1;
|
||||
pAlloc->used = s_uUsedFlag;
|
||||
pItem->type = HB_IT_NIL;
|
||||
|
||||
pItem->type = HB_IT_NIL;
|
||||
HB_GC_LOCK
|
||||
hb_gcLink( &s_pLockedBlock, pAlloc );
|
||||
HB_GC_UNLOCK
|
||||
|
||||
HB_GC_LOCK
|
||||
hb_gcLink( &s_pLockedBlock, pAlloc );
|
||||
HB_GC_UNLOCK
|
||||
if( pOrigin )
|
||||
hb_itemCopy( pItem, pOrigin );
|
||||
|
||||
if( pOrigin )
|
||||
hb_itemCopy( pItem, pOrigin );
|
||||
|
||||
return pItem;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
return pItem;
|
||||
}
|
||||
|
||||
void hb_gcGripDrop( HB_ITEM_PTR pItem )
|
||||
@@ -701,9 +676,14 @@ void hb_gcCollectAll( HB_BOOL fForce )
|
||||
#ifdef HB_GC_AUTO
|
||||
/* store number of marked blocks for automatic GC activation */
|
||||
s_ulBlocksMarked = s_ulBlocks;
|
||||
s_ulBlocksCheck = s_ulBlocksMarked + HB_GC_AUTO_CHECK;
|
||||
if( s_ulBlocksCheck <= s_ulBlocksMarked )
|
||||
if( s_ulBlocksAuto == 0 )
|
||||
s_ulBlocksCheck = HB_GC_AUTO_MAX;
|
||||
else
|
||||
{
|
||||
s_ulBlocksCheck = s_ulBlocksMarked + s_ulBlocksAuto;
|
||||
if( s_ulBlocksCheck <= s_ulBlocksMarked )
|
||||
s_ulBlocksCheck = HB_GC_AUTO_MAX;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* call memory manager cleanup function */
|
||||
@@ -814,3 +794,31 @@ HB_FUNC( HB_GCALL )
|
||||
|
||||
hb_gcCollectAll( hb_pcount() < 1 || hb_parl( 1 ) );
|
||||
}
|
||||
|
||||
#ifdef HB_GC_AUTO
|
||||
HB_FUNC( HB_GCSETAUTO )
|
||||
{
|
||||
HB_PTRUINT nBlocks, nPrevBlocks;
|
||||
HB_BOOL fSet = HB_ISNUM( 1 );
|
||||
|
||||
nBlocks = fSet ? hb_parnint( 1 ) * 1000 : 0;
|
||||
|
||||
HB_GC_LOCK
|
||||
nPrevBlocks = s_ulBlocksAuto;
|
||||
if( fSet )
|
||||
{
|
||||
s_ulBlocksAuto = nBlocks;
|
||||
if( s_ulBlocksAuto == 0 )
|
||||
s_ulBlocksCheck = HB_GC_AUTO_MAX;
|
||||
else
|
||||
{
|
||||
s_ulBlocksCheck = s_ulBlocksMarked + s_ulBlocksAuto;
|
||||
if( s_ulBlocksCheck <= s_ulBlocksMarked )
|
||||
s_ulBlocksCheck = HB_GC_AUTO_MAX;
|
||||
}
|
||||
}
|
||||
HB_GC_UNLOCK
|
||||
|
||||
hb_retnint( nPrevBlocks / 1000 );
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user