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
This commit is contained in:
Przemyslaw Czerpak
2008-09-19 20:28:26 +00:00
parent dd5f48d252
commit 7cc11cf5e2
10 changed files with 392 additions and 160 deletions

View File

@@ -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 <miguelangel@marchuet.net>
* contrib/hbbmcdx/bmdbfcdx.c
* source/rdd/dbfcdx/dbfcdx1.c

View File

@@ -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 )
{

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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++ )

View File

@@ -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 */

View File

@@ -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;
}
}

View File

@@ -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 );
}