diff --git a/harbour/ChangeLog b/harbour/ChangeLog index dde18a6899..8702bf90ae 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,29 @@ +2001-03-16 16:10 UTC+0100 Ryszard Glab + + *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 * contrib/libmisc/Makefile diff --git a/harbour/doc/en/garbage.txt b/harbour/doc/en/garbage.txt index cece9592aa..8dc80b495f 100644 --- a/harbour/doc/en/garbage.txt +++ b/harbour/doc/en/garbage.txt @@ -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 - * -------------- - * - * 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 * ---------------------- * @@ -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$ - * 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$ - * 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$ */ diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index fc21ba71cf..be3ece5af5 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -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 */ diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index 4934a2a539..708348b30e 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -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; diff --git a/harbour/source/rdd/dbfntx/dbfntx1.c b/harbour/source/rdd/dbfntx/dbfntx1.c index 3733350921..bea09e9fc7 100644 --- a/harbour/source/rdd/dbfntx/dbfntx1.c +++ b/harbour/source/rdd/dbfntx/dbfntx1.c @@ -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; */ diff --git a/harbour/source/rdd/workarea.c b/harbour/source/rdd/workarea.c index 607c6cd883..c1b49d86b9 100644 --- a/harbour/source/rdd/workarea.c +++ b/harbour/source/rdd/workarea.c @@ -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 ) diff --git a/harbour/source/rtl/errorapi.c b/harbour/source/rtl/errorapi.c index f4979b48ae..8428eccdfe 100644 --- a/harbour/source/rtl/errorapi.c +++ b/harbour/source/rtl/errorapi.c @@ -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 */ diff --git a/harbour/source/rtl/idle.c b/harbour/source/rtl/idle.c index 5baf43d113..896933b46c 100644 --- a/harbour/source/rtl/idle.c +++ b/harbour/source/rtl/idle.c @@ -58,8 +58,10 @@ #include #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; } } diff --git a/harbour/source/rtl/setkey.c b/harbour/source/rtl/setkey.c index 44baaa5218..0af2351407 100644 --- a/harbour/source/rtl/setkey.c +++ b/harbour/source/rtl/setkey.c @@ -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 { diff --git a/harbour/source/vm/garbage.c b/harbour/source/vm/garbage.c index 74cdaede2b..3c302d4887 100644 --- a/harbour/source/vm/garbage.c +++ b/harbour/source/vm/garbage.c @@ -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 ); diff --git a/harbour/source/vm/itemapi.c b/harbour/source/vm/itemapi.c index a0a14df125..f71c5bc2d7 100644 --- a/harbour/source/vm/itemapi.c +++ b/harbour/source/vm/itemapi.c @@ -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