ChangeLog 2001-03-16 16:10 UTC+0100

This commit is contained in:
Ryszard Glab
2001-03-16 15:01:20 +00:00
parent a19a8c4bab
commit d82a9ea53c
11 changed files with 120 additions and 247 deletions

View File

@@ -1,3 +1,29 @@
2001-03-16 16:10 UTC+0100 Ryszard Glab <rglab@imid.med.pl>
*doc/en/garbage.txt
*include/hbapi.h
*source/vm/garbage.c
*source/vm/itemapi.c
* new functions: hb_gcGripGet() and hb_gcGripDrop() for dynamic
allocation/deallocation of items
* added redefinition of _getGrip/_dropGrip to use
hb_gcGripGet/hb_gcGripDrop
* items allocated with hb_itemNew() or direct _getGrip() calls are
maintained properly by the Garbage Collector - there is no need
to locking/unlocking such items.
* removed no longer needed hb_gcLockItem/hb_gcUnlockItem
*source/rdd/dbcmd.c
*source/rdd/workarea.c
*source/rdd/dbfntx/dbfntx1.c
*source/rtl/errorapi.c
*source/rtl/idle.c
*source/rtl/setkey.c
* removed no longer needed calls for hb_gcLockItem/hb_gcUnlockItem
NOTE: there is no hb_gcLockItem/hb_gcUnlockItem functions - please remove
calls for these functions from your code.
2001-03-15 17:00 UTC-0500 David G. Holm <dholm@jsd-llc.com>
* contrib/libmisc/Makefile

View File

@@ -29,24 +29,16 @@
* and are stored in class shared variables.
*
* In special cases when the value of a harbour variable is stored internally
* in some static area (at C or assembler level), for example SETKEY()
* stores codeblocks that will be evaluated when a key is pressed,
* the garbage collector will be not able to scan such values since it
* doesn't know their location. This could cause some memory blocks to be
* released prematurely. To prevent the premature deallocation of such memory
* blocks they have to be locked for the garbage collector. The memory block
* can be locked with hb_gcLockItem() (recommended method) if
* harbour item structure is used or hb_gcLock() function if a direct memory
* pointer is used. The memory block can be unlocked by hb_gcUnlockItem() or
* hb_gcUnlock().
* in some static area (at C or assembler level), the garbage collector will
* be not able to scan such values since it doesn't know their location. This
* could cause some memory blocks to be released prematurely. To prevent the
* premature deallocation of such memory blocks the static data have to store
* a pointer to the value created with hb_itemNew() function.
* Example:
* static HB_ITEM s_item; // this item can be released by the GC
*
* Notice however that all variables passed to a low level function are
* passed via the eval stack, so they don't require locking during the
* function call. The locking will be required if a passed value is copied
* into some static area to make it available for other low-level functions
* called after the exit from function that stored the value. This is required
* because the value is removed from the eval stack after the function call and
* it can be no longer be referenced by other variables.
* static HB_ITEM_PTR pItem; // this item will be maintained correctly
* pItem = hb_itemNew( hb_param(1, IT_BLOCK) );
*
* However, scanning of all variables can be a time consuming operation. It
* requires that all allocated arrays have to be traversed through all their
@@ -68,15 +60,6 @@
* function calls. Memory allocated by hb_gcAlloc() should be released with
* hb_gcFree() function.
*
* Locking memory </par>
* --------------
*
* The memory allocated with hb_gcAlloc() should be locked to prevent
* automatic releasing if such a memory pointer is not stored within a
* harbour level variable. All harbour values (items) stored internally
* in static C area have to be locked.
* See hb_gcLockItem() and hb_gcUnlockItem() for more information.
*
* The garbage collecting </par>
* ----------------------
*
@@ -110,7 +93,7 @@
* See HB_GCALL() for explanation of how to call this function from your
* harbour code.
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem(),hb_gcCollectAll(),hb_gcItemRef(),HB_GCALL(),HB_IDLESTATE()
* hb_gcAlloc(),hb_gcFree(),hb_gcCollectAll(),hb_gcItemRef(),HB_GCALL(),HB_IDLESTATE()
* $END$
*/
@@ -157,7 +140,7 @@
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
* hb_gcFree()
* $END$
*/
@@ -189,87 +172,7 @@
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcLockItem(),hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcLockItem()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Locks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcLockItem( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* <pItem> The pointer to item structure that will be locked. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are locked only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcLockItem() is used to lock the memory pointer stored in
* the passed item structure. It suppres the memory releasing
* if the garbage collector will not find any reference to this
* pointer. The garbage collector is storing the lock counter -
* every call of this function increases the counter. The item is
* locked if this counter is greather then 0.
* $EXAMPLES$
* See source/rtl/setkey.c
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcUnlockItem()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* hb_gcUnlockItem()
* $CATEGORY$
* The garbage collector
* $ONELINER$
* Unlocks the memory to prevent deallocation by the garbage collector.
* $SYNTAX$
* void hb_gcUnlockItem( HB_ITEM_PTR pItem );
* $ARGUMENTS$
* <pItem> The pointer to item structure that will be unlocked. The
* passed item can be of any datatype although arrays, objects
* and codeblocks are unlocked only. Other datatypes don't require
* locking so they are simply ignored.
* $RETURNS$
* Nothing.
* $DESCRIPTION$
* hb_gcUnlockItem() is used to unlock the memory pointer stored in
* the passed item structure that was previously locked with
* hb_gcLockItem() call. It allows to release the memory during
* garbage collecting if the garbage collector will not find any
* reference to this pointer. The garbage collector is storing the
* lock counter - every call of this function decreases the counter.
* This function doesn't deallocate memory stored inside the item -
* the memory can be deallocated however during the closest garbage
* collecting if the lock counter is equal to 0 and the memory pointer
* is not referenced by any harbour level variable.
* $EXAMPLES$
* See source/rtl/setkey.c
* $STATUS$
* C
* $COMPLIANCE$
* This function is a Harbour extension
* $PLATFORMS$
* All
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem()
* hb_gcAlloc()
* $END$
*/
@@ -300,7 +203,7 @@
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
* hb_gcAlloc(),hb_gcFree()
* $END$
*/
@@ -340,7 +243,7 @@
* $FILES$
* source/vm/garbage.c
* $SEEALSO$
* hb_gcAlloc(),hb_gcFree(),hb_gcLockItem(),hb_gcUnlockItem()
* hb_gcAlloc(),hb_gcFree()
* $END$
*/

View File

@@ -511,12 +511,15 @@ extern char * hb_macroGetType( HB_ITEM_PTR pItem ); /* determine the type of an
typedef HB_GARBAGE_FUNC( HB_GARBAGE_FUNC_ );
typedef HB_GARBAGE_FUNC_ *HB_GARBAGE_FUNC_PTR;
extern HB_ITEM_PTR hb_gcGripGet( HB_ITEM_PTR pItem );
extern void hb_gcGripDrop( HB_ITEM_PTR pItem );
#define _getGrip hb_gcGripGet
#define _getDrop hb_gcGripDrop
extern void * hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pFunc ); /* allocates a memory controlled by the garbage collector */
extern void hb_gcFree( void *pAlloc ); /* deallocates a memory allocated by the garbage collector */
extern void * hb_gcLock( void *pAlloc ); /* do not release passed memory block */
extern void * hb_gcUnlock( void *pAlloc ); /* passed block is allowed to be released */
extern void hb_gcLockItem( HB_ITEM_PTR pItem ); /* do not release a memory block stored inside an item */
extern void hb_gcUnlockItem( HB_ITEM_PTR pItem ); /* allow to release the item */
extern void hb_gcCollect( void ); /* checks if a single memory block can be released */
extern void hb_gcCollectAll( void ); /* checks if all memory blocks can be released */
extern void hb_gcItemRef( HB_ITEM_PTR pItem ); /* checks if passed item refers passed memory block pointer */

View File

@@ -2222,7 +2222,6 @@ HB_FUNC( ORDCONDSET )
{
lpdbOrdCondInfo->itmCobFor = hb_itemNew( NULL );
hb_itemCopy( lpdbOrdCondInfo->itmCobFor, pItem );
hb_gcLockItem( lpdbOrdCondInfo->itmCobFor );
}
else
lpdbOrdCondInfo->itmCobFor = NULL;
@@ -2236,7 +2235,6 @@ HB_FUNC( ORDCONDSET )
{
lpdbOrdCondInfo->itmCobWhile = hb_itemNew( NULL );
hb_itemCopy( lpdbOrdCondInfo->itmCobWhile, pItem );
hb_gcLockItem( lpdbOrdCondInfo->itmCobWhile );
}
else
lpdbOrdCondInfo->itmCobWhile = NULL;
@@ -2246,7 +2244,6 @@ HB_FUNC( ORDCONDSET )
{
lpdbOrdCondInfo->itmCobEval = hb_itemNew( NULL );
hb_itemCopy( lpdbOrdCondInfo->itmCobEval, pItem );
hb_gcLockItem( lpdbOrdCondInfo->itmCobEval );
}
else
lpdbOrdCondInfo->itmCobEval = NULL;
@@ -2834,7 +2831,6 @@ HB_FUNC( DBSETRELATION )
dbRelations.lpaChild = ( AREAP ) s_pArea->pArea;
dbRelations.itmCobExpr = hb_itemNew( hb_param( 2, HB_IT_BLOCK ) );
hb_gcLockItem( dbRelations.itmCobExpr );
dbRelations.abKey = hb_itemNew( hb_param( 3, HB_IT_STRING ) );
dbRelations.isScoped = ( hb_pcount() > 3 )? hb_parl( 4 ):0;
dbRelations.lpdbriNext = NULL;

View File

@@ -1730,11 +1730,7 @@ static LPTAGINFO hb_ntxTagNew( LPNTXINDEX PIF, char * ITN, char *szKeyExpr, PHB_
strcpy( pTag->ForExpr, szForExp );
}
pTag->pKeyItem = pKeyExpr;
if( pTag->pKeyItem )
hb_gcLockItem( pTag->pKeyItem );
pTag->pForItem = pForExp;
if( pTag->pForItem )
hb_gcLockItem( pTag->pForItem );
pTag->AscendKey = fAscendKey;
pTag->UniqueKey = fUnique;
pTag->KeyType = bKeyType;
@@ -1777,14 +1773,12 @@ static void hb_ntxIndexFree( LPNTXINDEX pIndex )
hb_xfree( pTag->ForExpr );
if( pTag->pKeyItem != NULL )
{
hb_gcUnlockItem( pTag->pKeyItem );
if( hb_itemType( pTag->pKeyItem ) != HB_IT_BLOCK )
hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ) );
hb_itemRelease( pTag->pKeyItem );
}
if( pTag->pForItem != NULL )
{
hb_gcUnlockItem( pTag->pForItem );
hb_itemRelease( pTag->pForItem );
}
hb_ntxKeyFree( pTag->CurKeyInfo );
@@ -1821,7 +1815,6 @@ static ERRCODE hb_ntxHeaderLoad( LPNTXINDEX pIndex , char *ITN)
pTag->KeyExpr = (char *) hb_xgrab( NTX_MAX_KEY );
strcpy( pTag->KeyExpr, Header.key_expr );
pTag->pKeyItem = pKeyExp;
hb_gcLockItem( pTag->pKeyItem );
pTag->AscendKey = 1; /* fAscendKey; */
pTag->UniqueKey = Header.unique;
pTag->KeyType = 'C'; /* bKeyType; */

View File

@@ -500,17 +500,14 @@ ERRCODE hb_waOrderCondition( AREAP pArea, LPDBORDERCONDINFO param )
hb_xfree( pArea->lpdbOrdCondInfo->abFor );
if( pArea->lpdbOrdCondInfo->itmCobFor )
{
hb_gcUnlockItem( pArea->lpdbOrdCondInfo->itmCobFor );
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobFor );
}
if( pArea->lpdbOrdCondInfo->itmCobWhile )
{
hb_gcUnlockItem( pArea->lpdbOrdCondInfo->itmCobWhile );
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobWhile );
}
if( pArea->lpdbOrdCondInfo->itmCobEval )
{
hb_gcUnlockItem( pArea->lpdbOrdCondInfo->itmCobEval );
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobEval );
}
hb_xfree( pArea->lpdbOrdCondInfo );
@@ -706,7 +703,6 @@ ERRCODE hb_waClearRel( AREAP pArea )
if( lpdbRelation->itmCobExpr )
{
hb_gcUnlockItem( lpdbRelation->itmCobExpr );
hb_itemRelease( lpdbRelation->itmCobExpr );
}
if( lpdbRelation->abKey )
@@ -829,7 +825,6 @@ ERRCODE hb_waClearFilter( AREAP pArea )
/* Free all items */
if( pArea->dbfi.itmCobExpr )
{
hb_gcUnlockItem(pArea->dbfi.itmCobExpr);
hb_itemRelease( pArea->dbfi.itmCobExpr );
pArea->dbfi.itmCobExpr = NULL;
}
@@ -852,7 +847,6 @@ ERRCODE hb_waClearLocate( AREAP pArea )
/* Free all items */
if( pArea->dbsi.itmCobFor )
{
hb_gcUnlockItem( pArea->dbsi.itmCobFor );
hb_itemRelease( pArea->dbsi.itmCobFor );
pArea->dbsi.itmCobFor = NULL;
}
@@ -863,7 +857,6 @@ ERRCODE hb_waClearLocate( AREAP pArea )
}
if( pArea->dbsi.itmCobWhile )
{
hb_gcUnlockItem( pArea->dbsi.itmCobWhile );
hb_itemRelease( pArea->dbsi.itmCobWhile );
pArea->dbsi.itmCobWhile = NULL;
}
@@ -917,7 +910,6 @@ ERRCODE hb_waSetFilter( AREAP pArea, LPDBFILTERINFO pFilterInfo )
if( pFilterInfo->itmCobExpr )
{
pArea->dbfi.itmCobExpr = hb_itemNew( pFilterInfo->itmCobExpr );
hb_gcLockItem(pArea->dbfi.itmCobExpr);
}
if( pFilterInfo->abFilterText )
@@ -939,7 +931,6 @@ ERRCODE hb_waSetLocate( AREAP pArea, LPDBSCOPEINFO pScopeInfo )
if( pScopeInfo->itmCobFor )
{
pArea->dbsi.itmCobFor = hb_itemNew( pScopeInfo->itmCobFor );
hb_gcLockItem( pArea->dbsi.itmCobFor );
}
if( pScopeInfo->lpstrFor )
@@ -948,7 +939,6 @@ ERRCODE hb_waSetLocate( AREAP pArea, LPDBSCOPEINFO pScopeInfo )
if( pScopeInfo->itmCobWhile )
{
pArea->dbsi.itmCobWhile = hb_itemNew( pScopeInfo->itmCobWhile );
hb_gcLockItem( pArea->dbsi.itmCobWhile );
}
if( pScopeInfo->lpstrWhile )

View File

@@ -109,10 +109,7 @@ HB_FUNC( ERRORBLOCK )
if( pNewErrorBlock )
{
if( HB_IS_BLOCK( &oldError ) )
hb_gcUnlockItem( &oldError ); /* allow release for garbage collector */
hb_itemCopy( &s_errorBlock, pNewErrorBlock );
hb_gcLockItem( pNewErrorBlock ); /* lock it in case it is not stored inside of harbour variable */
}
hb_itemReturn( &oldError );
@@ -199,11 +196,6 @@ USHORT hb_errLaunch( PHB_ITEM pError )
if( s_iLaunchCount == HB_ERROR_LAUNCH_MAX )
hb_errInternal( HB_EI_ERRTOOMANY, NULL, NULL, NULL );
/* Lock an item to prevent deallocation by the GC - the error object
* can be not assigned to any harbour level variable
*/
hb_gcLockItem( pError );
/* Launch the error handler: "lResult := EVAL( ErrorBlock(), oError )" */
s_iLaunchCount++;
@@ -221,7 +213,6 @@ USHORT hb_errLaunch( PHB_ITEM pError )
else
pResult = hb_itemDo( &s_errorBlock, 1, pError );
hb_gcUnlockItem( pError );
s_iLaunchCount--;
/* Check results */
@@ -308,11 +299,6 @@ PHB_ITEM hb_errLaunchSubst( PHB_ITEM pError )
if( s_iLaunchCount == HB_ERROR_LAUNCH_MAX )
hb_errInternal( HB_EI_ERRTOOMANY, NULL, NULL, NULL );
/* Lock an item to prevent deallocation by the GC - the error object
* can be not assigned to any harbour level variable
*/
hb_gcLockItem( pError );
/* Launch the error handler: "xResult := EVAL( ErrorBlock(), oError )" */
s_iLaunchCount++;
@@ -330,7 +316,6 @@ PHB_ITEM hb_errLaunchSubst( PHB_ITEM pError )
else
pResult = hb_itemDo( &s_errorBlock, 1, pError );
hb_gcUnlockItem( pError );
s_iLaunchCount--;
/* Check results */

View File

@@ -58,8 +58,10 @@
#include <time.h>
#endif
/* list of background tasks */
static HB_ITEM_PTR s_pIdleTasks = NULL;
/* list of background tasks
* A pointer into an array of pointers to items with a codeblock
*/
static HB_ITEM_PTR * s_pIdleTasks = NULL;
/* flag to prevent recursive calls of hb_idleState() */
static BOOL s_bIamIdle = FALSE;
@@ -141,7 +143,7 @@ void hb_idleState( void )
if( s_pIdleTasks && s_uiIdleTask < s_uiIdleMaxTask )
{
hb_vmEvalBlock( s_pIdleTasks + s_uiIdleTask );
hb_vmEvalBlock( s_pIdleTasks[ s_uiIdleTask ] );
++s_uiIdleTask;
s_bIamIdle = FALSE;
return;
@@ -177,13 +179,11 @@ void hb_idleShutDown( void )
{
if( s_pIdleTasks )
{
HB_ITEM_PTR pItem = s_pIdleTasks;
while( s_uiIdleMaxTask-- )
do
{
hb_gcUnlock( pItem->item.asBlock.value );
hb_itemClear( pItem );
++pItem;
hb_itemRelease( s_pIdleTasks[ --s_uiIdleMaxTask ] );
}
while( s_uiIdleMaxTask );
hb_xfree( s_pIdleTasks );
s_pIdleTasks = NULL;
}
@@ -211,18 +211,18 @@ HB_FUNC( HB_IDLEADD )
++s_uiIdleMaxTask;
if( !s_pIdleTasks )
{
s_pIdleTasks = ( HB_ITEM_PTR ) hb_xgrab( sizeof( HB_ITEM ) );
s_pIdleTasks = ( HB_ITEM_PTR * ) hb_xgrab( sizeof( HB_ITEM_PTR ) );
}
else
{
s_pIdleTasks = ( HB_ITEM_PTR ) hb_xrealloc( s_pIdleTasks, sizeof( HB_ITEM ) * s_uiIdleMaxTask );
s_pIdleTasks = ( HB_ITEM_PTR * ) hb_xrealloc( s_pIdleTasks, sizeof( HB_ITEM_PTR ) * s_uiIdleMaxTask );
}
hb_itemCopy( s_pIdleTasks + s_uiIdleMaxTask - 1, pBlock );
/* prevent releasing if this block if it is no longer stored inside of
* a harbour variable
*/
hb_gcLockItem( pBlock );
/* store a copy of passed codeblock
*/
s_pIdleTasks[ s_uiIdleMaxTask - 1 ] = hb_itemNew( pBlock );
/* return a pointer as a handle to this idle task
*/
hb_retnl( ( ULONG ) pBlock->item.asBlock.value ); /* TODO: access to pointers from harbour code */
}
else
@@ -238,14 +238,14 @@ HB_FUNC( HB_IDLEDEL )
{
SHORT iTask;
ULONG ulID = hb_parnl( 1 ); /* TODO: access to pointers from harbour code */
HB_ITEM_PTR pItem = s_pIdleTasks;
HB_ITEM_PTR pItem;
iTask = 0;
while( iTask < s_uiIdleMaxTask && !bFound )
{
pItem = s_pIdleTasks[ iTask ];
if( ulID == ( ULONG ) pItem->item.asBlock.value )
{
hb_gcUnlockItem( pItem );
hb_itemClear( hb_itemReturn( pItem ) ); /* return a codeblock */
--s_uiIdleMaxTask;
@@ -253,8 +253,8 @@ HB_FUNC( HB_IDLEDEL )
{
if( iTask != s_uiIdleMaxTask )
memcpy( &s_pIdleTasks[ iTask ], &s_pIdleTasks[ iTask + 1 ],
sizeof( HB_ITEM ) * (s_uiIdleMaxTask - iTask) );
s_pIdleTasks = ( HB_ITEM_PTR ) hb_xrealloc( s_pIdleTasks, sizeof( HB_ITEM ) * s_uiIdleMaxTask );
sizeof( HB_ITEM_PTR ) * (s_uiIdleMaxTask - iTask) );
s_pIdleTasks = ( HB_ITEM_PTR * ) hb_xrealloc( s_pIdleTasks, sizeof( HB_ITEM_PTR ) * s_uiIdleMaxTask );
}
else
{
@@ -263,7 +263,6 @@ HB_FUNC( HB_IDLEDEL )
}
bFound = TRUE;
}
++pItem;
++iTask;
}
}

View File

@@ -65,11 +65,9 @@ void hb_setkeyExit( void )
{
PHB_SETKEY sk_list_tmp;
hb_gcUnlockItem( s_sk_list->pAction );
hb_itemRelease( s_sk_list->pAction );
if( s_sk_list->pIsActive )
{
hb_gcUnlockItem( s_sk_list->pIsActive );
hb_itemRelease( s_sk_list->pIsActive );
}
sk_list_tmp = s_sk_list->next;
@@ -109,10 +107,6 @@ static void sk_add( BOOL bReturn, SHORT iKeyCode, PHB_ITEM pAction, PHB_ITEM pIs
sk_list_tmp->iKeyCode = iKeyCode;
sk_list_tmp->pAction = hb_itemNew( pAction );
sk_list_tmp->pIsActive = pIsActive ? hb_itemNew( pIsActive ) : NULL;
/* lock codeblock to prevent deallocation by the GC */
hb_gcLockItem( sk_list_tmp->pAction );
if( sk_list_tmp->pIsActive )
hb_gcLockItem( sk_list_tmp->pIsActive );
if( sk_list_end == NULL )
s_sk_list = sk_list_tmp;
@@ -129,11 +123,9 @@ static void sk_add( BOOL bReturn, SHORT iKeyCode, PHB_ITEM pAction, PHB_ITEM pIs
/* Free the previous values */
hb_gcUnlockItem( sk_list_tmp->pAction );
hb_itemRelease( sk_list_tmp->pAction );
if( sk_list_tmp->pIsActive )
{
hb_gcUnlockItem( sk_list_tmp->pIsActive );
hb_itemRelease( sk_list_tmp->pIsActive );
}
/* Set the new values or free the entry */
@@ -142,10 +134,6 @@ static void sk_add( BOOL bReturn, SHORT iKeyCode, PHB_ITEM pAction, PHB_ITEM pIs
{
sk_list_tmp->pAction = hb_itemNew( pAction );
sk_list_tmp->pIsActive = pIsActive ? hb_itemNew( pIsActive ) : NULL;
/* lock codeblock to prevent deallocation by the GC */
hb_gcLockItem( sk_list_tmp->pAction );
if( sk_list_tmp->pIsActive )
hb_gcLockItem( sk_list_tmp->pIsActive );
}
else
{

View File

@@ -146,6 +146,58 @@ void hb_gcFree( void *pBlock )
}
}
static HB_GARBAGE_FUNC( hb_gcGripRelease )
{
/* Item was already released in hb_gcGripDrop() - then we have nothing
* to do here
*/
HB_SYMBOL_UNUSED( Cargo );
}
HB_ITEM_PTR hb_gcGripGet( HB_ITEM_PTR pOrigin )
{
HB_GARBAGE_PTR pAlloc;
pAlloc = HB_GARBAGE_NEW( sizeof( HB_ITEM ) + sizeof( HB_GARBAGE ) );
if( pAlloc )
{
HB_ITEM_PTR pItem = ( HB_ITEM_PTR )( pAlloc + 1 );
hb_gcLink( &s_pLockedBlock, pAlloc );
pAlloc->pFunc = hb_gcGripRelease;
pAlloc->locked = 1;
pAlloc->used = s_uUsedFlag;
if( pOrigin )
{
pItem->type = HB_IT_NIL;
hb_itemCopy( pItem, pOrigin );
}
else
{
memset( pItem, 0, sizeof( HB_ITEM ) );
pItem->type = HB_IT_NIL;
}
return pItem;
}
else
return NULL;
}
void hb_gcGripDrop( HB_ITEM_PTR pItem )
{
if( pItem )
{
HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem;
--pAlloc;
hb_itemClear( pItem ); /* clear value stored in this item */
hb_gcUnlink( &s_pLockedBlock, pAlloc );
HB_GARBAGE_FREE( pAlloc );
}
}
/* Lock a memory pointer so it will not be released if stored
outside of harbour variables
*/
@@ -190,29 +242,6 @@ void *hb_gcUnlock( void *pBlock )
return pBlock;
}
/* Lock an item so it will not be released if stored
outside of harbour variables
*/
void hb_gcLockItem( HB_ITEM_PTR pItem )
{
if( HB_IS_ARRAY( pItem ) )
hb_gcLock( pItem->item.asArray.value );
else if( HB_IS_BLOCK( pItem ) )
hb_gcLock( pItem->item.asBlock.value );
}
/* Unlock an item so it can be released if there is no
references inside of harbour variables
*/
void hb_gcUnlockItem( HB_ITEM_PTR pItem )
{
if( HB_IS_ARRAY( pItem ) )
hb_gcUnlock( pItem->item.asArray.value );
else if( HB_IS_BLOCK( pItem ) )
hb_gcUnlock( pItem->item.asBlock.value );
}
/* Mark a passed item as used so it will be not released by the GC
*/
void hb_gcItemRef( HB_ITEM_PTR pItem )
@@ -304,31 +333,9 @@ void hb_gcCollectAll( void )
pAlloc = s_pLockedBlock;
do
{ /* it is not very elegant method but it works well */
if( pAlloc->pFunc == hb_arrayReleaseGarbage )
if( pAlloc->pFunc == hb_gcGripRelease )
{
HB_BASEARRAY_PTR pArray = ( HB_BASEARRAY_PTR ) ( pAlloc + 1 );
ULONG ulSize = pArray->ulLen;
HB_ITEM_PTR pItem;
/* mark as used all elements in locked array */
pItem = pArray->pItems;
while( ulSize )
{
hb_gcItemRef( pItem++ );
--ulSize;
}
} /* it is not very elegant method but it works well */
else if( pAlloc->pFunc == hb_codeblockDeleteGarbage )
{
HB_CODEBLOCK_PTR pCBlock = ( HB_CODEBLOCK_PTR ) ( pAlloc + 1 );
USHORT ui = 1;
/* mark as used all detached variables in locked codeblock */
while( ui <= pCBlock->uiLocals )
{
hb_gcItemRef( &pCBlock->pLocals[ ui ] );
++ui;
}
hb_gcItemRef( ( HB_ITEM_PTR ) ( pAlloc + 1 ) );
}
pAlloc = pAlloc->pNext;
} while ( s_pLockedBlock != pAlloc );

View File

@@ -322,24 +322,9 @@ PHB_ITEM hb_itemDoC( char * szFunc, USHORT uiPCount, PHB_ITEM pItemArg1, ... )
PHB_ITEM hb_itemNew( PHB_ITEM pNull )
{
PHB_ITEM pItem;
HB_TRACE(HB_TR_DEBUG, ("hb_itemNew(%p)", pNull));
pItem = ( PHB_ITEM ) hb_xgrab( sizeof( HB_ITEM ) );
if( pNull )
{
pItem->type = HB_IT_NIL;
hb_itemCopy( pItem, pNull );
}
else
{
memset( pItem, 0, sizeof( HB_ITEM ) );
pItem->type = HB_IT_NIL;
}
return pItem;
return hb_gcGripGet( pNull );
}
PHB_ITEM hb_itemParam( USHORT uiParam )
@@ -380,9 +365,7 @@ BOOL hb_itemRelease( PHB_ITEM pItem )
if( pItem )
{
hb_itemClear( pItem );
hb_xfree( pItem );
hb_gcGripDrop( pItem );
return TRUE;
}
else