From 7cc11cf5e25d2aaa450a55d46447212e1b9c08e2 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Fri, 19 Sep 2008 20:28:26 +0000 Subject: [PATCH] 2008-09-19 22:27 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/source/vm/set.c ! fixed casting * harbour/contrib/xhb/xhbcopyf.c * replaced TABs with SPACEs * harbour/include/hbapirdd.h * harbour/source/rdd/workarea.c * harbour/source/rdd/wacore.c * harbour/source/rdd/wafunc.c + added support for detaching and attaching workareas * harbour/source/vm/hvm.c % minor cleanup in thread return code * harbour/include/hbthread.h * harbour/source/vm/thread.c * unlock HVM stack during thread join operation * added workaround for DosWaitThread() which seems to fail if thread terminated before ; added TOFIX note for OS2 and join code --- harbour/ChangeLog | 23 ++ harbour/contrib/xhb/xhbcopyf.c | 2 +- harbour/include/hbapirdd.h | 11 +- harbour/include/hbthread.h | 2 +- harbour/source/rdd/wacore.c | 372 +++++++++++++++++++++++++-------- harbour/source/rdd/wafunc.c | 45 ++++ harbour/source/rdd/workarea.c | 55 +---- harbour/source/vm/hvm.c | 10 +- harbour/source/vm/set.c | 2 +- harbour/source/vm/thread.c | 30 +-- 10 files changed, 392 insertions(+), 160 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 886f453d8f..7ae6bbfdb5 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,29 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-09-19 22:27 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/vm/set.c + ! fixed casting + + * harbour/contrib/xhb/xhbcopyf.c + * replaced TABs with SPACEs + + * harbour/include/hbapirdd.h + * harbour/source/rdd/workarea.c + * harbour/source/rdd/wacore.c + * harbour/source/rdd/wafunc.c + + added support for detaching and attaching workareas + + * harbour/source/vm/hvm.c + % minor cleanup in thread return code + + * harbour/include/hbthread.h + * harbour/source/vm/thread.c + * unlock HVM stack during thread join operation + * added workaround for DosWaitThread() which seems to fail if thread + terminated before + ; added TOFIX note for OS2 and join code + 2008-09-19 12:21 UTC+0100 Miguel Angel Marchuet * contrib/hbbmcdx/bmdbfcdx.c * source/rdd/dbfcdx/dbfcdx1.c diff --git a/harbour/contrib/xhb/xhbcopyf.c b/harbour/contrib/xhb/xhbcopyf.c index ba8a03caeb..3a7dac8845 100644 --- a/harbour/contrib/xhb/xhbcopyf.c +++ b/harbour/contrib/xhb/xhbcopyf.c @@ -102,7 +102,7 @@ static BOOL hb_fsCopy( char * szSource, char * szDest, PHB_ITEM pBlock ) bRetVal = TRUE; if( hb_itemType( pBlock ) != HB_IT_BLOCK ) - pBlock = NULL; + pBlock = NULL; while( ( usRead = hb_fsRead( fhndSource, buffer, BUFFER_SIZE ) ) != 0 ) { diff --git a/harbour/include/hbapirdd.h b/harbour/include/hbapirdd.h index a8c3dc2040..8e604face5 100644 --- a/harbour/include/hbapirdd.h +++ b/harbour/include/hbapirdd.h @@ -1149,8 +1149,12 @@ typedef RDDNODE * LPRDDNODE; * PROTOTYPES * ---------- */ -/* RDD virtual machine integration functions */ + +/* internal RDD functions */ +extern void hb_rddCloseDetachedAreas( void ); + +/* RDD virtual machine integration functions */ extern HB_EXPORT void hb_rddShutDown( void ); extern HB_EXPORT ERRCODE hb_rddGetFieldValue( HB_ITEM_PTR pItem, PHB_SYMB pFieldSymbol ); extern HB_EXPORT ERRCODE hb_rddPutFieldValue( HB_ITEM_PTR pItem, PHB_SYMB pFieldSymbol ); @@ -1214,6 +1218,11 @@ extern HB_EXPORT ERRCODE hb_rddTransRecords( const char *szCpId, PHB_ITEM pDelim ); extern HB_EXPORT void hb_tblStructure( AREAP pArea, PHB_ITEM pStruct, USHORT uiSize ); +extern HB_EXPORT ERRCODE hb_rddCloseAllParentRelations( AREAP pArea ); + +extern HB_EXPORT ERRCODE hb_rddDetachArea( AREAP pArea, PHB_ITEM pCargo ); +extern HB_EXPORT AREAP hb_rddRequestArea( char * szAlias, PHB_ITEM pCargo, + BOOL fNewArea, BOOL fWait ); #if 0 extern HB_EXPORT ERRCODE hb_rddDisinherit( const char * drvName ); diff --git a/harbour/include/hbthread.h b/harbour/include/hbthread.h index 3b51f97c52..ce6915b4c2 100644 --- a/harbour/include/hbthread.h +++ b/harbour/include/hbthread.h @@ -301,7 +301,7 @@ extern void hb_threadMutexNotify( PHB_ITEM pItem, PHB_ITEM pNotifier, BOOL f extern PHB_ITEM hb_threadMutexSubscribe( PHB_ITEM pItem, BOOL fClear ); extern PHB_ITEM hb_threadMutexTimedSubscribe( PHB_ITEM pItem, ULONG ulMilliSec, BOOL fClear ); -#if defined( HB_MT_VM ) && defined( _HB_API_INTERNAL_ ) /* && defined( HB_STACK_MACROS ) */ +#if defined( HB_MT_VM ) && defined( _HB_API_INTERNAL_ ) extern void hb_threadMutexUnlockAll( void ); diff --git a/harbour/source/rdd/wacore.c b/harbour/source/rdd/wacore.c index 5e37d3563d..9075a39631 100644 --- a/harbour/source/rdd/wacore.c +++ b/harbour/source/rdd/wacore.c @@ -57,21 +57,8 @@ #include "hbapierr.h" #include "hbvm.h" #include "hbstack.h" +#include "hbthread.h" -#if 0 -/* Default RDD name */ -static AREAP * s_waList = NULL; /* Allocated WorkAreas */ -static USHORT s_uiWaMax = 0; /* Number of allocated WA */ -static USHORT s_uiWaSpace = 0; /* Number of allocated WA */ - -static USHORT * s_waNums = NULL; /* Allocated WorkAreas */ -static USHORT s_uiWaNumMax = 0; /* Number of allocated WA */ - -static USHORT s_uiCurrArea = 1; /* Current WokrArea number */ -static AREAP s_pCurrArea = NULL; /* Current WorkArea pointer */ - -static BOOL s_fNetError = FALSE; /* Error on Networked environments */ -#endif #define HB_SET_WA( n ) do \ { \ @@ -83,59 +70,11 @@ static BOOL s_fNetError = FALSE; /* Error on Networked environments */ /* - * Return the next free WorkArea for later use. + * Insert new WorkArea node at current WA position */ -HB_EXPORT ERRCODE hb_rddSelectFirstAvailable( void ) +static void hb_waNodeInsert( PHB_STACKRDD pRddInfo, AREAP pArea ) { - PHB_STACKRDD pRddInfo; - USHORT uiArea; - - HB_TRACE(HB_TR_DEBUG, ("hb_rddSelectFirstAvailable()")); - - pRddInfo = hb_stackRDD(); - - uiArea = 1; - while( uiArea < pRddInfo->uiWaNumMax ) - { - if( pRddInfo->waNums[ uiArea ] == 0 ) - break; - uiArea++; - } - if( uiArea >= HB_RDD_MAX_AREA_NUM ) - return FAILURE; - HB_SET_WA( uiArea ); - return SUCCESS; -} - -/* - * Insert the new WorkArea node - */ -HB_EXPORT USHORT hb_rddInsertAreaNode( const char *szDriver ) -{ - USHORT uiRddID, uiWaPos; - PHB_STACKRDD pRddInfo; - LPRDDNODE pRddNode; - AREAP pArea; - - HB_TRACE(HB_TR_DEBUG, ("hb_rddInsertAreaNode(%s)", szDriver)); - - pRddInfo = hb_stackRDD(); - if( pRddInfo->uiCurrArea && pRddInfo->pCurrArea ) - return 0; - - pRddNode = hb_rddFindNode( szDriver, &uiRddID ); - if( !pRddNode ) - return 0; - - pArea = ( AREAP ) hb_rddNewAreaNode( pRddNode, uiRddID ); - if( !pArea ) - return 0; - - if( pRddInfo->uiCurrArea == 0 ) - { - if( hb_rddSelectFirstAvailable() != SUCCESS ) - return 0; - } + USHORT uiWaPos; if( pRddInfo->uiCurrArea >= pRddInfo->uiWaNumMax ) { @@ -183,35 +122,17 @@ HB_EXPORT USHORT hb_rddInsertAreaNode( const char *szDriver ) uiWaPos--; } } - pRddInfo->waList[ uiWaPos ] = pArea; pRddInfo->waNums[ pRddInfo->uiCurrArea ] = uiWaPos; - pRddInfo->pCurrArea = pRddInfo->waList[ uiWaPos ]; - ( ( AREAP ) pRddInfo->pCurrArea )->uiArea = pRddInfo->uiCurrArea; - - return pRddInfo->uiCurrArea; + pRddInfo->pCurrArea = pRddInfo->waList[ uiWaPos ] = pArea; + pArea->uiArea = pRddInfo->uiCurrArea; } /* - * Closes and releases the current WorkArea preparing it - * to be used with a new database. + * Remove current WorkArea node */ -HB_EXPORT void hb_rddReleaseCurrentArea( void ) +static void hb_waNodeDelete( PHB_STACKRDD pRddInfo ) { - PHB_STACKRDD pRddInfo; USHORT uiWaPos; - AREAP pArea; - - HB_TRACE(HB_TR_DEBUG, ("hb_rddReleaseCurrentArea()")); - - pRddInfo = hb_stackRDD(); - pArea = ( AREAP ) pRddInfo->pCurrArea; - if( !pArea ) - return; - - if( SELF_CLOSE( pArea ) == FAILURE ) - return; - - SELF_RELEASE( pArea ); uiWaPos = pRddInfo->waNums[ pRddInfo->uiCurrArea ]; pRddInfo->waNums[ pRddInfo->uiCurrArea ] = 0; @@ -242,6 +163,90 @@ HB_EXPORT void hb_rddReleaseCurrentArea( void ) pRddInfo->pCurrArea = NULL; } +/* + * Return the next free WorkArea for later use. + */ +HB_EXPORT ERRCODE hb_rddSelectFirstAvailable( void ) +{ + PHB_STACKRDD pRddInfo; + USHORT uiArea; + + HB_TRACE(HB_TR_DEBUG, ("hb_rddSelectFirstAvailable()")); + + pRddInfo = hb_stackRDD(); + + uiArea = 1; + while( uiArea < pRddInfo->uiWaNumMax ) + { + if( pRddInfo->waNums[ uiArea ] == 0 ) + break; + uiArea++; + } + if( uiArea >= HB_RDD_MAX_AREA_NUM ) + return FAILURE; + HB_SET_WA( uiArea ); + return SUCCESS; +} + +/* + * Creare and insert the new WorkArea node + */ +HB_EXPORT USHORT hb_rddInsertAreaNode( const char *szDriver ) +{ + PHB_STACKRDD pRddInfo; + LPRDDNODE pRddNode; + USHORT uiRddID; + AREAP pArea; + + HB_TRACE(HB_TR_DEBUG, ("hb_rddInsertAreaNode(%s)", szDriver)); + + pRddInfo = hb_stackRDD(); + if( pRddInfo->uiCurrArea && pRddInfo->pCurrArea ) + return 0; + + pRddNode = hb_rddFindNode( szDriver, &uiRddID ); + if( !pRddNode ) + return 0; + + pArea = ( AREAP ) hb_rddNewAreaNode( pRddNode, uiRddID ); + if( !pArea ) + return 0; + + if( pRddInfo->uiCurrArea == 0 ) + { + if( hb_rddSelectFirstAvailable() != SUCCESS ) + return 0; + } + + hb_waNodeInsert( pRddInfo, pArea ); + + return pRddInfo->uiCurrArea; +} + +/* + * Closes and releases the current WorkArea preparing it + * to be used with a new database. + */ +HB_EXPORT void hb_rddReleaseCurrentArea( void ) +{ + PHB_STACKRDD pRddInfo; + AREAP pArea; + + HB_TRACE(HB_TR_DEBUG, ("hb_rddReleaseCurrentArea()")); + + pRddInfo = hb_stackRDD(); + pArea = ( AREAP ) pRddInfo->pCurrArea; + if( !pArea ) + return; + + if( SELF_CLOSE( pArea ) == FAILURE ) + return; + + SELF_RELEASE( pArea ); + + hb_waNodeDelete( pRddInfo ); +} + /* * Closes all WorkAreas. */ @@ -446,3 +451,196 @@ HB_EXPORT ERRCODE hb_rddSelectWorkAreaNumber( int iArea ) return ( pRddInfo->pCurrArea == NULL ) ? FAILURE : SUCCESS; } + + +/* *********************************************************** */ + +/* + * Moving work ares between threads + */ + +static HB_CRITICAL_NEW( s_waMtx ); +static HB_COND_NEW( s_waCond ); +static PHB_ITEM s_pDetachedAreas = NULL; + +static HB_GARBAGE_FUNC( hb_waHolderDestructor ) +{ + AREAP * pHolder = ( AREAP * ) Cargo; + + if( *pHolder ) + { + AREAP pArea; + int iArea; + + pArea = *pHolder; + *pHolder = NULL; + + iArea = hb_rddGetCurrentWorkAreaNumber(); + + hb_rddSelectFirstAvailable(); + hb_waNodeInsert( hb_stackRDD(), pArea ); + hb_rddReleaseCurrentArea(); + + hb_rddSelectWorkAreaNumber( iArea ); + } +} + +void hb_rddCloseDetachedAreas( void ) +{ + PHB_ITEM pDetachedArea; + + /* protect by critical section access to s_pDetachedAreas array */ + hb_threadEnterCriticalSection( &s_waMtx ); + pDetachedArea = s_pDetachedAreas; + s_pDetachedAreas = NULL; + /* leave critical section */ + hb_threadLeaveCriticalSection( &s_waMtx ); + /* release detached areas */ + if( pDetachedArea ) + hb_itemRelease( pDetachedArea ); +} + +HB_EXPORT ERRCODE hb_rddDetachArea( AREAP pArea, PHB_ITEM pCargo ) +{ + AREAP * pHolder; + PHB_ITEM pDetachedArea; + ULONG ulPos; + int iArea; + + HB_TRACE(HB_TR_DEBUG, ("hb_rddDetachArea(%p,%p)", pArea, pCargo)); + + /* save current WA number */ + iArea = hb_rddGetCurrentWorkAreaNumber(); + /* select given WA */ + hb_rddSelectWorkAreaNumber( pArea->uiArea ); + /* flush buffers */ + SELF_GOCOLD( pArea ); + /* remove all locks */ + /* ??? is it xbase++ compatible? */ + /* SELF_UNLOCK( pArea, NULL ); */ + /* Clear all child and parent relations */ + SELF_CLEARREL( pArea ); + hb_rddCloseAllParentRelations( pArea ); + /* detach WA and alias */ + hb_waNodeDelete( hb_stackRDD() ); + pArea->uiArea = 0; + if( pArea->atomAlias ) + hb_dynsymSetAreaHandle( ( PHB_DYNS ) pArea->atomAlias, 0 ); + /* restore previous WA number */ + hb_rddSelectWorkAreaNumber( iArea ); + + /* protect by critical section access to s_pDetachedAreas array */ + hb_threadEnterCriticalSection( &s_waMtx ); + if( ! s_pDetachedAreas ) + { + s_pDetachedAreas = hb_itemArrayNew( 1 ); + ulPos = 1; + } + else + { + ulPos = hb_arrayLen( s_pDetachedAreas ) + 1; + hb_arraySize( s_pDetachedAreas, ulPos ); + } + pDetachedArea = hb_arrayGetItemPtr( s_pDetachedAreas, ulPos ); + hb_arrayNew( pDetachedArea, 2 ); + if( pCargo ) + hb_arraySet( pDetachedArea, 2, pCargo ); + pHolder = ( AREAP * ) hb_gcAlloc( sizeof( AREAP ), hb_waHolderDestructor ); + *pHolder = pArea; + hb_itemPutPtrGC( hb_arrayGetItemPtr( pDetachedArea, 1 ), pHolder ); + /* siagnal waiting processes that new area is available */ + hb_threadCondBroadcast( &s_waCond ); + /* leave critical section */ + hb_threadLeaveCriticalSection( &s_waMtx ); + + return SUCCESS; +} + +HB_EXPORT AREAP hb_rddRequestArea( char * szAlias, PHB_ITEM pCargo, + BOOL fNewArea, BOOL fWait ) +{ + PHB_DYNS pSymAlias = NULL; + AREAP pArea = NULL; + + if( pCargo ) + hb_itemClear( pCargo ); + + /* close current WA or chose 1-st free available */ + if( !fNewArea ) + { + hb_rddReleaseCurrentArea(); + } + else if( hb_rddSelectFirstAvailable() != SUCCESS ) + { + hb_errRT_DBCMD( EG_ARG, EDBCMD_BADPARAMETER, NULL, HB_ERR_FUNCNAME ); + return NULL; + } + + if( szAlias ) + { + pSymAlias = hb_dynsymFindName( szAlias ); + + /* verify if the alias name is valid symbol */ + if( hb_rddVerifyAliasName( szAlias ) != SUCCESS ) + { + hb_errRT_DBCMD_Ext( EG_BADALIAS, EDBCMD_BADALIAS, NULL, szAlias, EF_CANDEFAULT ); + return NULL; + } + /* verify if the alias is already in use */ + if( hb_dynsymAreaHandle( pSymAlias ) != 0 ) + { + hb_errRT_DBCMD_Ext( EG_DUPALIAS, EDBCMD_DUPALIAS, NULL, szAlias, EF_CANDEFAULT ); + return NULL; + } + } + + /* protect by critical section access to s_pDetachedAreas array */ + hb_threadEnterCriticalSection( &s_waMtx ); + for( ;; ) + { + if( s_pDetachedAreas ) + { + ULONG ulLen = hb_arrayLen( s_pDetachedAreas ), ulPos = 1; + if( pSymAlias ) + { + for( ulPos = 1; ulPos <= ulLen; ++ulPos ) + { + AREAP * pDetachedArea = ( AREAP * ) + hb_arrayGetPtr( hb_arrayGetItemPtr( s_pDetachedAreas, ulPos ), 1 ); + if( pSymAlias == ( PHB_DYNS ) ( *pDetachedArea )->atomAlias ) + break; + } + } + if( ulPos <= ulLen ) + { + PHB_ITEM pArray = hb_arrayGetItemPtr( s_pDetachedAreas, ulPos ); + AREAP * pDetachedArea = ( AREAP * ) hb_arrayGetPtr( pArray, 1 ); + + pArea = *pDetachedArea; + *pDetachedArea = NULL; + if( pCargo ) + hb_arrayGet( pArray, 2, pCargo ); + hb_arrayDel( s_pDetachedAreas, ulPos ); + hb_arraySize( s_pDetachedAreas, ulLen - 1 ); + } + } + + if( pArea || !fWait ) + break; + + hb_vmUnlock(); + /* wait for detached workareas */ + hb_threadCondWait( &s_waCond, &s_waMtx ); + hb_vmLock(); + if( hb_vmRequestQuery() != 0 ) + break; + } + /* leave critical section */ + hb_threadLeaveCriticalSection( &s_waMtx ); + + /* atach WA and set alias */ + if( pArea ) + hb_waNodeInsert( hb_stackRDD(), pArea ); + + return pArea; +} diff --git a/harbour/source/rdd/wafunc.c b/harbour/source/rdd/wafunc.c index 8d66170fc6..ef4fc859d7 100644 --- a/harbour/source/rdd/wafunc.c +++ b/harbour/source/rdd/wafunc.c @@ -1133,3 +1133,48 @@ ERRCODE hb_rddTransRecords( AREAP pArea, return errCode; } + +static ERRCODE hb_rddCloseParentRel( AREAP pArea, void * pChildArea ) +{ + if( pArea->lpdbRelations ) + { + LPDBRELINFO * lpdbRelationPtr = &pArea->lpdbRelations; + USHORT uiArea = ( ( AREAP ) pChildArea )->uiArea; + + do + { + LPDBRELINFO lpdbRelation = *lpdbRelationPtr; + + if( lpdbRelation->lpaChild->uiArea == uiArea ) + { + /* Clear this relation */ + hb_rddSelectWorkAreaNumber( lpdbRelation->lpaChild->uiArea ); + SELF_CHILDEND( lpdbRelation->lpaChild, lpdbRelation ); + if( lpdbRelation->itmCobExpr ) + hb_itemRelease( lpdbRelation->itmCobExpr ); + if( lpdbRelation->abKey ) + hb_itemRelease( lpdbRelation->abKey ); + + *lpdbRelationPtr = lpdbRelation->lpdbriNext; + hb_xfree( lpdbRelation ); + } + else + lpdbRelationPtr = &lpdbRelation->lpdbriNext; + } + while ( *lpdbRelationPtr ); + } + return SUCCESS; +} + +/* close all parent relations */ +ERRCODE hb_rddCloseAllParentRelations( AREAP pArea ) +{ + ERRCODE errCode = SUCCESS; + + HB_TRACE(HB_TR_DEBUG, ("hb_rddCloseAllParentRelations(%p)", pArea)); + + if( pArea->uiParents > 0 ) + errCode = hb_rddIterateWorkAreas( hb_rddCloseParentRel, pArea ); + + return errCode; +} diff --git a/harbour/source/rdd/workarea.c b/harbour/source/rdd/workarea.c index 45ef340a73..e621433a3c 100644 --- a/harbour/source/rdd/workarea.c +++ b/harbour/source/rdd/workarea.c @@ -655,52 +655,6 @@ static ERRCODE hb_waAlias( AREAP pArea, BYTE * szAlias ) return SUCCESS; } -/* - * Close the table in the WorkArea - helper function - */ -static ERRCODE hb_waCloseAux( AREAP pArea, void * pChildArea ) -{ - USHORT uiPrevArea, uiArea; - LPDBRELINFO lpdbRelation, lpdbRelPrev, lpdbRelTmp; - - uiArea = ( ( AREAP ) pChildArea )->uiArea; - if( pArea->lpdbRelations ) - { - uiPrevArea = hb_rddGetCurrentWorkAreaNumber(); - lpdbRelation = pArea->lpdbRelations; - lpdbRelPrev = NULL; - while( lpdbRelation ) - { - if( lpdbRelation->lpaChild->uiArea == uiArea ) - { - /* Clear this relation */ - hb_rddSelectWorkAreaNumber( lpdbRelation->lpaChild->uiArea ); - SELF_CHILDEND( lpdbRelation->lpaChild, lpdbRelation ); - hb_rddSelectWorkAreaNumber( uiPrevArea ); - if( lpdbRelation->itmCobExpr ) - { - hb_itemRelease( lpdbRelation->itmCobExpr ); - } - if( lpdbRelation->abKey ) - hb_itemRelease( lpdbRelation->abKey ); - lpdbRelTmp = lpdbRelation; - if( lpdbRelPrev ) - lpdbRelPrev->lpdbriNext = lpdbRelation->lpdbriNext; - else - pArea->lpdbRelations = lpdbRelation->lpdbriNext; - lpdbRelation = lpdbRelation->lpdbriNext; - hb_xfree( lpdbRelTmp ); - } - else - { - lpdbRelPrev = lpdbRelation; - lpdbRelation = lpdbRelation->lpdbriNext; - } - } - } - return SUCCESS; -} - /* * Close the table in the WorkArea. */ @@ -713,11 +667,8 @@ static ERRCODE hb_waClose( AREAP pArea ) SELF_CLEARREL( pArea ); SELF_CLEARLOCATE( pArea ); - if( pArea->uiParents > 0 ) - { - /* Clear relations that has this area as a child */ - hb_rddIterateWorkAreas( hb_waCloseAux, pArea ); - } + /* Clear relations that has this area as a child */ + hb_rddCloseAllParentRelations( pArea ); if( pArea->atomAlias ) hb_dynsymSetAreaHandle( ( PHB_DYNS ) pArea->atomAlias, 0 ); @@ -2136,6 +2087,8 @@ HB_EXPORT void hb_rddShutDown( void ) HB_TRACE(HB_TR_DEBUG, ("hb_rddShutDown()")); + hb_rddCloseDetachedAreas(); + if( s_uiRddCount > 0 ) { for( uiCount = 0; uiCount < s_uiRddCount; uiCount++ ) diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index ec8a9c4cfb..9a4c1ac765 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -704,13 +704,13 @@ HB_EXPORT void hb_vmThreadQuit( void ) if( HB_IS_BYREF( pReturn ) ) pReturn = hb_itemUnRef( pReturn ); - if( !pState->pResult ) - pState->pResult = hb_itemNew( NULL ); - hb_itemMove( pState->pResult, pReturn ); + if( !pState->pResult ) + pState->pResult = hb_itemNew( pReturn ); + else + hb_itemCopy( pState->pResult, pReturn ); } - else - hb_itemClear( hb_stackReturnItem() ); + hb_itemClear( hb_stackReturnItem() ); hb_rddCloseAll(); /* close all workareas */ hb_stackRemove( 1 ); /* clear stack items, leave only initial symbol item */ diff --git a/harbour/source/vm/set.c b/harbour/source/vm/set.c index bd3abaadaa..c8055733eb 100644 --- a/harbour/source/vm/set.c +++ b/harbour/source/vm/set.c @@ -209,7 +209,7 @@ static HB_FHANDLE open_handle( PHB_SET_STRUCT pSet, const char * file_name, BOOL ( hb_strnicmp( pFilename->szName, "COM", 3 ) == 0 && pFilename->szName[3] >= '1' && pFilename->szName[3] <= '9' ) ) ) ) { - hb_strupr( pFilename->szName ); + hb_strupr( ( char * ) pFilename->szName ); def_ext = NULL; } } diff --git a/harbour/source/vm/thread.c b/harbour/source/vm/thread.c index 83ac92535e..0b2b1e63f9 100644 --- a/harbour/source/vm/thread.c +++ b/harbour/source/vm/thread.c @@ -373,7 +373,12 @@ BOOL hb_threadJoin( HB_THREAD_T th_id ) } return FALSE; #elif defined( HB_OS_OS2 ) - return DosWaitThread( &th_id, DCWW_WAIT ) == NO_ERROR; + APIRET rc = DosWaitThread( &th_id, DCWW_WAIT ); + /* TOFIX: ERROR_INVALID_THREADID is a hack for failing DosWaitThread() + * when thread terminates before DosWaitThread() call. + * OS2 users please check and fix this code if possible. + */ + return rc == NO_ERROR || rc == ERROR_INVALID_THREADID; #else { int TODO_MT; } return FALSE; @@ -390,14 +395,8 @@ BOOL hb_threadDetach( HB_THREAD_T th_id ) #elif defined( HB_OS_WIN_32 ) return CloseHandle( th_id ) != 0; #elif defined( HB_OS_OS2 ) - /* TODO: I do not know clean method of running thread detaching - * In OS/2. - * After termination the HVM threads are detached automatically - * by GC but it may not clean allocated OS resources if caller - * does not keep thread pointer item alive and the cleanup code - * will be executed by THIS thread. - */ - return DosWaitThread( &th_id, DCWW_NOWAIT ) == NO_ERROR; + APIRET rc = DosWaitThread( &th_id, DCWW_NOWAIT ); + return rc == NO_ERROR || rc == ERROR_INVALID_THREADID; #else { int TODO_MT; } return FALSE; @@ -505,7 +504,6 @@ static PHB_THREADSTATE hb_thParam( int iParam ) return NULL; } - HB_FUNC( HB_THREADSTART ) { PHB_ITEM pStart = hb_param( 1, HB_IT_ANY ); @@ -562,10 +560,16 @@ HB_FUNC( HB_THREADJOIN ) { BOOL fResult = FALSE; - if( pThread->th_id && hb_threadJoin( pThread->th_id ) ) + if( pThread->th_id ) + { + hb_vmUnlock(); + fResult = hb_threadJoin( pThread->th_id ); + if( fResult ) + pThread->th_id = 0; + hb_vmLock(); + } + if( fResult ) { - pThread->th_id = 0; - fResult = TRUE; if( pThread->pResult ) hb_itemParamStore( 2, pThread->pResult ); }