diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 22ca1f1b1d..11959734cf 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,21 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-10-06 15:30 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbthread.h + * harbour/source/vm/thread.c + * harbour/source/vm/hvm.c + + add numeric HVM thread identifiers to thread structure. Now + HB_THREADID() returns numbers in all OSes + + * harbour/include/hbexprop.h + * harbour/include/hbexprb.c + * harbour/source/common/expropt2.c + + added compile time optimization for MIN() and MAX() functions + + * harbour/source/rtl/minmax.c + * removed trailing spaces from source code + 2008-10-06 12:38 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbclass.ch * harbour/include/hboo.ch diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index 635071705f..83ec4045d0 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -1654,6 +1654,16 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall ) if( usCount && HB_SUPPORT_HARBOUR ) hb_compExprReduceCTOD( pSelf, HB_COMP_PARAM ); } + else if( strcmp( "MIN", pName->value.asSymbol ) == 0 ) + { + if( usCount == 2 && HB_SUPPORT_HARBOUR ) + hb_compExprReduceMIN( pSelf, HB_COMP_PARAM ); + } + else if( strcmp( "MAX", pName->value.asSymbol ) == 0 ) + { + if( usCount == 2 && HB_SUPPORT_HARBOUR ) + hb_compExprReduceMAX( pSelf, HB_COMP_PARAM ); + } else if( strcmp( "UPPER", pName->value.asSymbol ) == 0 ) { if( usCount ) @@ -1762,7 +1772,7 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall ) HB_EXPR_PTR pArg = pParms->value.asList.pExprList; char buf[ 16 ]; BOOL fStrict; - + /* TODO: warning message does not fit very well, because it requires type of used parameter. Let's print "unknown", to avoid deeper analysis of parameter. @@ -1848,7 +1858,7 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall ) snprintf( buf, sizeof( buf ), "%d", (int) usCount ); hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_PARAM_COUNT, buf, "1 or 2" ); } - + /* hb_i18n_gettext_noop() is not a real function. It is used to force writing of string to .pot file. So, we should try to replaced function call by first argument regardless fI18n flag diff --git a/harbour/include/hbexprop.h b/harbour/include/hbexprop.h index 785902c937..e69e90fd0f 100644 --- a/harbour/include/hbexprop.h +++ b/harbour/include/hbexprop.h @@ -203,6 +203,8 @@ extern BOOL hb_compExprReduceSTOD( HB_EXPR_PTR, USHORT usCount, HB_COMP_DECL ); extern BOOL hb_compExprReduceDTOS( HB_EXPR_PTR, HB_COMP_DECL ); extern BOOL hb_compExprReduceCTOD( HB_EXPR_PTR, HB_COMP_DECL ); extern BOOL hb_compExprReduceUPPER( HB_EXPR_PTR, HB_COMP_DECL ); +extern BOOL hb_compExprReduceMIN( HB_EXPR_PTR, HB_COMP_DECL ); +extern BOOL hb_compExprReduceMAX( HB_EXPR_PTR, HB_COMP_DECL ); extern BOOL hb_compExprReduceBitFunc( HB_EXPR_PTR, HB_LONG, BOOL, HB_COMP_DECL ); extern void hb_compI18nAdd( HB_COMP_DECL, const char* szText, const char* szContext, UINT uiLine ); diff --git a/harbour/include/hbthread.h b/harbour/include/hbthread.h index bc3646cdd3..ab5f5a95aa 100644 --- a/harbour/include/hbthread.h +++ b/harbour/include/hbthread.h @@ -99,8 +99,9 @@ HB_EXTERN_BEGIN #if defined( HB_PTHREAD_API ) + typedef HB_LONG HB_THREAD_NO; typedef pthread_t HB_THREAD_ID; - typedef pthread_t HB_THREAD_T; + typedef pthread_t HB_THREAD_HANDLE; typedef pthread_mutex_t HB_RAWCRITICAL_T; typedef pthread_cond_t HB_RAWCOND_T; @@ -139,8 +140,9 @@ HB_EXTERN_BEGIN # define HB_MAX_THREAD 32768 + typedef HB_LONG HB_THREAD_NO; typedef unsigned HB_THREAD_ID; - typedef HANDLE HB_THREAD_T; + typedef HANDLE HB_THREAD_HANDLE; typedef CRITICAL_SECTION HB_RAWCRITICAL_T; typedef HANDLE HB_RAWCOND_T; @@ -184,8 +186,14 @@ HB_EXTERN_BEGIN #elif defined( HB_OS_OS2 ) + /* In OS2 thread ID is continuous integer number so we can use it directly + * anyhow I'd prefer to not make such strict binding to OS values because + * it make cause troubles when code will be ported to other platforms. + */ + /* typedef TID HB_THREAD_NO; */ + typedef HB_LONG HB_THREAD_NO; typedef TID HB_THREAD_ID; - typedef TID HB_THREAD_T; + typedef TID HB_THREAD_HANDLE; typedef HMTX HB_RAWCRITICAL_T; typedef HEV HB_RAWCOND_T; @@ -210,8 +218,9 @@ HB_EXTERN_BEGIN #else + typedef int HB_THREAD_NO; typedef int HB_THREAD_ID; - typedef int HB_THREAD_T; + typedef int HB_THREAD_HANDLE; typedef int HB_CRITICAL_T; typedef int HB_RAWCRITICAL_T; typedef int HB_COND_T; @@ -273,7 +282,9 @@ typedef struct _HB_THREADSTATE PHB_ITEM pMemvars; PHB_ITEM pResult; PHB_ITEM pThItm; - HB_THREAD_T th_id; + HB_THREAD_NO th_no; + HB_THREAD_ID th_id; + HB_THREAD_HANDLE th_h; struct _HB_THREADSTATE * pPrev; struct _HB_THREADSTATE * pNext; } HB_THREADSTATE, * PHB_THREADSTATE; @@ -292,9 +303,9 @@ extern BOOL hb_threadCondBroadcast( HB_COND_T * cond ); extern BOOL hb_threadCondWait( HB_COND_T * cond, HB_CRITICAL_T * mutex ); extern BOOL hb_threadCondTimedWait( HB_COND_T * cond, HB_CRITICAL_T * mutex, ULONG ulMilliSec ); -extern HB_THREAD_T hb_threadCreate( PHB_THREAD_STARTFUNC start_func, void * Cargo ); -extern BOOL hb_threadJoin( HB_THREAD_T th_id ); -extern BOOL hb_threadDetach( HB_THREAD_T th_id ); +extern HB_THREAD_HANDLE hb_threadCreate( HB_THREAD_ID * th_id, PHB_THREAD_STARTFUNC start_func, void * Cargo ); +extern BOOL hb_threadJoin( HB_THREAD_HANDLE th_h ); +extern BOOL hb_threadDetach( HB_THREAD_HANDLE th_h ); /* used by .prg code */ extern PHB_ITEM hb_threadMutexCreate( BOOL fSync ); diff --git a/harbour/source/common/expropt2.c b/harbour/source/common/expropt2.c index 8c42e19aeb..363f866698 100644 --- a/harbour/source/common/expropt2.c +++ b/harbour/source/common/expropt2.c @@ -1904,6 +1904,144 @@ BOOL hb_compExprReduceUPPER( HB_EXPR_PTR pSelf, HB_COMP_DECL ) return FALSE; } +BOOL hb_compExprReduceMIN( HB_EXPR_PTR pSelf, HB_COMP_DECL ) +{ + HB_EXPR_PTR pParms = pSelf->value.asFunCall.pParms; + HB_EXPR_PTR pFirst = pParms->value.asList.pExprList; + HB_EXPR_PTR pNext = pFirst->pNext; + + if( pFirst->ExprType == pNext->ExprType ) + { + HB_EXPR_PTR pExpr = NULL; + + if( pNext->ExprType == HB_ET_NUMERIC ) + { + BYTE bType = ( pFirst->value.asNum.NumType & pNext->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + pExpr = pFirst->value.asNum.val.l <= pNext->value.asNum.val.l ? + pFirst : pNext; + break; + + case HB_ET_DOUBLE: + pExpr = pFirst->value.asNum.val.d <= pNext->value.asNum.val.d ? + pFirst : pNext; + break; + + default: + if( pFirst->value.asNum.NumType == HB_ET_DOUBLE ) + pExpr = pFirst->value.asNum.val.d <= ( double ) pNext->value.asNum.val.l ? + pFirst : pNext; + else + pExpr = ( double ) pFirst->value.asNum.val.l <= pNext->value.asNum.val.d ? + pFirst : pNext; + } + } + else if( pFirst->ExprType == HB_ET_DATE ) + { + pExpr = pFirst->value.asNum.val.l <= pNext->value.asNum.val.l ? + pFirst : pNext; + } + else if( pFirst->ExprType == HB_ET_LOGICAL ) + { + pExpr = !pFirst->value.asLogical ? pFirst : pNext; + } + + if( pExpr ) + { + HB_EXPR_PTR * pExprPtr = &pParms->value.asList.pExprList; + + while( *pExprPtr ) + { + if( *pExprPtr == pExpr ) + { + *pExprPtr = pExpr->pNext; + break; + } + pExprPtr = &( *pExprPtr )->pNext; + } + HB_COMP_EXPR_FREE( pParms ); + HB_COMP_EXPR_FREE( pSelf->value.asFunCall.pFunName ); + memcpy( pSelf, pExpr, sizeof( HB_EXPR ) ); + HB_COMP_EXPR_CLEAR( pExpr ); + return TRUE; + } + } + + return FALSE; +} + +BOOL hb_compExprReduceMAX( HB_EXPR_PTR pSelf, HB_COMP_DECL ) +{ + HB_EXPR_PTR pParms = pSelf->value.asFunCall.pParms; + HB_EXPR_PTR pFirst = pParms->value.asList.pExprList; + HB_EXPR_PTR pNext = pFirst->pNext; + + if( pFirst->ExprType == pNext->ExprType ) + { + HB_EXPR_PTR pExpr = NULL; + + if( pNext->ExprType == HB_ET_NUMERIC ) + { + BYTE bType = ( pFirst->value.asNum.NumType & pNext->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + pExpr = pFirst->value.asNum.val.l >= pNext->value.asNum.val.l ? + pFirst : pNext; + break; + + case HB_ET_DOUBLE: + pExpr = pFirst->value.asNum.val.d >= pNext->value.asNum.val.d ? + pFirst : pNext; + break; + + default: + if( pFirst->value.asNum.NumType == HB_ET_DOUBLE ) + pExpr = pFirst->value.asNum.val.d >= ( double ) pNext->value.asNum.val.l ? + pFirst : pNext; + else + pExpr = ( double ) pFirst->value.asNum.val.l >= pNext->value.asNum.val.d ? + pFirst : pNext; + } + } + else if( pFirst->ExprType == HB_ET_DATE ) + { + pExpr = pFirst->value.asNum.val.l >= pNext->value.asNum.val.l ? + pFirst : pNext; + } + else if( pFirst->ExprType == HB_ET_LOGICAL ) + { + pExpr = pFirst->value.asLogical ? pFirst : pNext; + } + + if( pExpr ) + { + HB_EXPR_PTR * pExprPtr = &pParms->value.asList.pExprList; + + while( * pExprPtr ) + { + if( * pExprPtr == pExpr ) + { + * pExprPtr = pExpr->pNext; + break; + } + pExprPtr = &( *pExprPtr )->pNext; + } + HB_COMP_EXPR_FREE( pParms ); + HB_COMP_EXPR_FREE( pSelf->value.asFunCall.pFunName ); + memcpy( pSelf, pExpr, sizeof( HB_EXPR ) ); + HB_COMP_EXPR_CLEAR( pExpr ); + return TRUE; + } + } + + return FALSE; +} + BOOL hb_compExprReduceBitFunc( HB_EXPR_PTR pSelf, HB_LONG lResult, BOOL fBool, HB_COMP_DECL ) { HB_EXPR_PTR pParms = pSelf->value.asFunCall.pParms; diff --git a/harbour/source/rtl/minmax.c b/harbour/source/rtl/minmax.c index 335a86aad9..494067b968 100644 --- a/harbour/source/rtl/minmax.c +++ b/harbour/source/rtl/minmax.c @@ -66,7 +66,7 @@ HB_FUNC( MAX ) { HB_LONG l1 = hb_itemGetNInt( p1 ); HB_LONG l2 = hb_itemGetNInt( p2 ); - + hb_retnint( l1 >= l2 ? l1 : l2 ); return; } @@ -74,13 +74,13 @@ HB_FUNC( MAX ) { double d1 = hb_itemGetND( p1 ); double d2 = hb_itemGetND( p2 ); - + int iDec1; int iDec2; - + hb_itemGetNLen( p1, NULL, &iDec1 ); hb_itemGetNLen( p2, NULL, &iDec2 ); - + if( d1 >= d2 ) hb_retndlen( d1, 0, iDec1 ); else @@ -91,14 +91,14 @@ HB_FUNC( MAX ) { BOOL b1 = hb_itemGetL( p1 ); BOOL b2 = hb_itemGetL( p2 ); - + hb_retl( b1 >= b2 ? b1 : b2 ); return; } else if( HB_IS_DATE( p1 ) && HB_IS_DATE( p2 ) ) { char szDate[ 9 ]; - + hb_retds( hb_itemGetDL( p1 ) >= hb_itemGetDL( p2 ) ? hb_pardsbuff( szDate, 1 ) : hb_pardsbuff( szDate, 2 ) ); return; } @@ -118,7 +118,7 @@ HB_FUNC( MIN ) { HB_LONG l1 = hb_itemGetNInt( p1 ); HB_LONG l2 = hb_itemGetNInt( p2 ); - + hb_retnint( l1 <= l2 ? l1 : l2 ); return; } @@ -126,13 +126,13 @@ HB_FUNC( MIN ) { double d1 = hb_itemGetND( p1 ); double d2 = hb_itemGetND( p2 ); - + int iDec1; int iDec2; - + hb_itemGetNLen( p1, NULL, &iDec1 ); hb_itemGetNLen( p2, NULL, &iDec2 ); - + if( d1 <= d2 ) hb_retndlen( d1, 0, iDec1 ); else @@ -143,14 +143,14 @@ HB_FUNC( MIN ) { BOOL b1 = hb_itemGetL( p1 ); BOOL b2 = hb_itemGetL( p2 ); - + hb_retl( b1 <= b2 ? b1 : b2 ); return; } else if( HB_IS_DATE( p1 ) && HB_IS_DATE( p2 ) ) { char szDate[ 9 ]; - + hb_retds( hb_itemGetDL( p1 ) <= hb_itemGetDL( p2 ) ? hb_pardsbuff( szDate, 1 ) : hb_pardsbuff( szDate, 2 ) ); return; } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 70d0c9f0f5..5b084cb422 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -390,6 +390,8 @@ static int volatile s_iStackCount = 0; static int volatile s_iRunningCount = 0; /* active HVM stacks list */ static PHB_THREADSTATE s_vmStackLst = NULL; +/* thread number */ +static HB_THREAD_NO s_threadNo = 0; # define HB_THREQUEST_STOP 1 # define HB_THREQUEST_QUIT 2 @@ -608,6 +610,8 @@ static void hb_vmStackAdd( PHB_THREADSTATE pState ) } s_iStackCount++; } + if( pState->th_no ) + pState->th_no = ++s_threadNo; } static void hb_vmStackDel( PHB_THREADSTATE pState ) diff --git a/harbour/source/vm/thread.c b/harbour/source/vm/thread.c index ee97ef3dea..90ba275795 100644 --- a/harbour/source/vm/thread.c +++ b/harbour/source/vm/thread.c @@ -354,45 +354,51 @@ BOOL hb_threadCondTimedWait( HB_COND_T * cond, HB_CRITICAL_T * mutex, ULONG ulMi #endif } -HB_THREAD_T hb_threadCreate( PHB_THREAD_STARTFUNC start_func, void * Cargo ) +HB_THREAD_HANDLE hb_threadCreate( HB_THREAD_ID * th_id, PHB_THREAD_STARTFUNC start_func, void * Cargo ) { - HB_THREAD_T th_id; + HB_THREAD_HANDLE th_h; #if !defined( HB_MT_VM ) HB_SYMBOL_UNUSED( start_func ); HB_SYMBOL_UNUSED( Cargo ); - th_id = 0; + *th_id = ( HB_THREAD_ID ) 0; + th_h = ( HB_THREAD_HANDLE ) 0; #elif defined( HB_PTHREAD_API ) - if( pthread_create( &th_id, NULL, start_func, Cargo ) != 0 ) - th_id = 0; + if( pthread_create( th_id, NULL, start_func, Cargo ) != 0 ) + *th_id = ( HB_THREAD_ID ) 0; + th_h = *th_id; #elif defined( HB_OS_WIN_32 ) - th_id = ( HANDLE ) _beginthreadex( NULL, 0, start_func, Cargo, 0, NULL ); + th_h = ( HANDLE ) _beginthreadex( NULL, 0, start_func, Cargo, 0, th_id ); + if( !th_h ) + *th_id = ( HB_THREAD_ID ) 0; #elif defined( HB_OS_OS2 ) - th_id = _beginthread( ( void * ) start_func, NULL, 128 * 1024, Cargo ); + *th_id = _beginthread( ( void * ) start_func, NULL, 128 * 1024, Cargo ); + th_h = *th_id; #else { int TODO_MT; } - th_id = 0; + *th_id = ( HB_THREAD_ID ) 0; + th_h = ( HB_THREAD_HANDLE ) 0; #endif - return th_id; + return th_h; } -BOOL hb_threadJoin( HB_THREAD_T th_id ) +BOOL hb_threadJoin( HB_THREAD_HANDLE th_h ) { #if !defined( HB_MT_VM ) - HB_SYMBOL_UNUSED( th_id ); + HB_SYMBOL_UNUSED( th_h ); return FALSE; #elif defined( HB_PTHREAD_API ) - return pthread_join( th_id, NULL ) == 0; + return pthread_join( th_h, NULL ) == 0; #elif defined( HB_OS_WIN_32 ) - if( WaitForSingleObject( th_id, INFINITE ) != WAIT_FAILED ) + if( WaitForSingleObject( th_h, INFINITE ) != WAIT_FAILED ) { - CloseHandle( th_id ); + CloseHandle( th_h ); return TRUE; } return FALSE; #elif defined( HB_OS_OS2 ) - APIRET rc = DosWaitThread( &th_id, DCWW_WAIT ); + APIRET rc = DosWaitThread( &th_h, 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. @@ -404,17 +410,17 @@ BOOL hb_threadJoin( HB_THREAD_T th_id ) #endif } -BOOL hb_threadDetach( HB_THREAD_T th_id ) +BOOL hb_threadDetach( HB_THREAD_HANDLE th_h ) { #if !defined( HB_MT_VM ) - HB_SYMBOL_UNUSED( th_id ); + HB_SYMBOL_UNUSED( th_h ); return FALSE; #elif defined( HB_PTHREAD_API ) - return pthread_detach( th_id ) == 0; + return pthread_detach( th_h ) == 0; #elif defined( HB_OS_WIN_32 ) - return CloseHandle( th_id ) != 0; + return CloseHandle( th_h ) != 0; #elif defined( HB_OS_OS2 ) - APIRET rc = DosWaitThread( &th_id, DCWW_NOWAIT ); + APIRET rc = DosWaitThread( &th_h, DCWW_NOWAIT ); return rc == NO_ERROR || rc == ERROR_INVALID_THREADID; #else { int TODO_MT; } @@ -453,10 +459,10 @@ static HB_GARBAGE_FUNC( hb_threadDestructor ) hb_xfree( pThread->pSet ); pThread->pSet = NULL; } - if( pThread->th_id != 0 ) + if( pThread->th_h != 0 ) { - hb_threadDetach( pThread->th_id ); - pThread->th_id = 0; + hb_threadDetach( pThread->th_h ); + pThread->th_h = 0; } } @@ -657,9 +663,9 @@ HB_FUNC( HB_THREADSTART ) #if defined( HB_MT_VM ) if( hb_vmThreadRegister( ( void * ) pThread ) ) #endif - pThread->th_id = hb_threadCreate( hb_threadStartVM, ( void * ) pReturn ); + pThread->th_h = hb_threadCreate( &pThread->th_id, hb_threadStartVM, ( void * ) pReturn ); - if( pThread->th_id == 0 ) + if( !pThread->th_h ) { #if defined( HB_MT_VM ) hb_vmThreadRelease( pThread ); @@ -692,7 +698,7 @@ HB_FUNC( HB_THREADID ) #if defined( HB_MT_VM ) PHB_THREADSTATE pThread = ( PHB_THREADSTATE ) hb_vmThreadState(); if( pThread ) - hb_retnint( ( HB_PTRDIFF ) pThread->th_id ); + hb_retnint( ( HB_PTRDIFF ) pThread->th_no ); else #endif hb_retnint( 0 ); @@ -706,12 +712,12 @@ HB_FUNC( HB_THREADJOIN ) { BOOL fResult = FALSE; - if( pThread->th_id ) + if( pThread->th_h ) { hb_vmUnlock(); - fResult = hb_threadJoin( pThread->th_id ); + fResult = hb_threadJoin( pThread->th_h ); if( fResult ) - pThread->th_id = 0; + pThread->th_h = 0; hb_vmLock(); } if( fResult ) @@ -735,9 +741,9 @@ HB_FUNC( HB_THREADDETACH ) { BOOL fResult = FALSE; - if( pThread->th_id && hb_threadDetach( pThread->th_id ) ) + if( pThread->th_h && hb_threadDetach( pThread->th_h ) ) { - pThread->th_id = 0; + pThread->th_h = 0; fResult = TRUE; } hb_retl( fResult );