From 423391977e1b8f61a7e59662cabead446528db1d Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Mon, 6 Oct 2008 00:19:10 +0000 Subject: [PATCH] 2008-10-06 02:18 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/tests/speedtst.prg * marked T054 as memory tests * harbour/source/vm/hvm.c * harbour/source/vm/thread.c * added hb_threadOnce( @ [, ] ) -> This function allow to execute some code only once. It's usefull in MT environment for initialization. is variable which holds the execution status and have to be initialized to NIL. In most of cases it will be simple static variable in user code. is optional codeblock which is executed only once (on 1-st call with given ) * harbour/source/rtl/filesys.c ! do not make any file name conversions in hb_fsNameConv() if HVM stack is not allocated * harbour/source/rtl/gtcrs/gtcrs.c * casting --- harbour/ChangeLog | 22 ++++++++++ harbour/source/rtl/filesys.c | 7 ++++ harbour/source/rtl/gtcrs/gtcrs.c | 2 +- harbour/source/vm/hvm.c | 2 +- harbour/source/vm/thread.c | 72 ++++++++++++++++++++++++++++---- harbour/tests/speedtst.prg | 56 +++++++++++++------------ 6 files changed, 126 insertions(+), 35 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 14956b243d..62b176697c 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,28 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-10-06 02:18 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/tests/speedtst.prg + * marked T054 as memory tests + + * harbour/source/vm/hvm.c + * harbour/source/vm/thread.c + * added hb_threadOnce( @ [, ] ) -> + This function allow to execute some code only once. It's usefull in + MT environment for initialization. + is variable which holds the execution status and have + to be initialized to NIL. In most of cases it will be simple static + variable in user code. + is optional codeblock which is executed only once (on 1-st + call with given ) + + * harbour/source/rtl/filesys.c + ! do not make any file name conversions in hb_fsNameConv() if HVM stack + is not allocated + + * harbour/source/rtl/gtcrs/gtcrs.c + * casting + 2008-10-06 01:06 UTC+0200 Viktor Szakats (harbour.01 syenar hu) * source/debug/debugger.prg * source/rtl/typefile.prg diff --git a/harbour/source/rtl/filesys.c b/harbour/source/rtl/filesys.c index 381060bfa2..ab8d5a91c9 100644 --- a/harbour/source/rtl/filesys.c +++ b/harbour/source/rtl/filesys.c @@ -3083,6 +3083,13 @@ HB_EXPORT BYTE * hb_fsNameConv( BYTE * szFileName, BOOL * pfFree ) TRIMFILENAME - strip trailing and leading spaces (also from extension) */ + if( !hb_stackId() ) + { + if( pfFree ) + *pfFree = FALSE; + return szFileName; + } + fTrim = hb_setGetTrimFileName(); cDirSep = hb_setGetDirSeparator(); iFileCase = hb_setGetFileCase(); diff --git a/harbour/source/rtl/gtcrs/gtcrs.c b/harbour/source/rtl/gtcrs/gtcrs.c index ed3634e3e1..ccf40e6278 100644 --- a/harbour/source/rtl/gtcrs/gtcrs.c +++ b/harbour/source/rtl/gtcrs/gtcrs.c @@ -1412,7 +1412,7 @@ static char *tiGetS( const char *capname ) { char *ptr; - ptr = tigetstr( capname ); + ptr = tigetstr( ( char * ) capname ); if ( ptr ) { if ( ptr == ( char * ) -1 ) diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 350221dae2..70d0c9f0f5 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -1031,10 +1031,10 @@ HB_EXPORT int hb_vmQuit( void ) hb_cdpReleaseAll(); /* releases codepages */ #endif hb_itemClear( hb_stackReturnItem() ); - hb_gcCollectAll( TRUE ); #if defined( HB_MT_VM ) + hb_threadExit(); hb_vmStackRelease(); /* release HVM stack and remove it from linked HVM stacks list */ #else hb_setRelease( hb_stackSetStruct() ); /* releases Sets */ diff --git a/harbour/source/vm/thread.c b/harbour/source/vm/thread.c index e86cf58a5d..c30dc14fe6 100644 --- a/harbour/source/vm/thread.c +++ b/harbour/source/vm/thread.c @@ -74,6 +74,7 @@ #endif static volatile BOOL s_fThreadInit = FALSE; +static PHB_ITEM s_pOnceMutex = NULL; #if !defined( HB_MT_VM ) /* nothing */ @@ -100,6 +101,8 @@ static volatile BOOL s_fThreadInit = FALSE; # if defined( HB_CRITICAL_INIT ) static HB_RAWCRITICAL_T s_critical_init; + static HB_RAWCRITICAL_T s_critical_once; + static HB_RAWCRITICAL_T s_critical_mtx; static void hb_threadCriticalInit( HB_CRITICAL_T * critical ) { if( !s_fThreadInit ) @@ -114,10 +117,12 @@ static volatile BOOL s_fThreadInit = FALSE; HB_CRITICAL_UNLOCK( s_critical_init ); } # else - static HB_CRITICAL_NEW( s_critical_init ); + static HB_CRITICAL_NEW( s_critical_once ); + static HB_CRITICAL_NEW( s_critical_mtx ); # endif # if defined( HB_COND_INIT ) + static HB_CRITICAL_NEW( s_critical_init ); static void hb_threadCondInit( HB_COND_T * cond ) { if( !s_fThreadInit ) @@ -147,6 +152,8 @@ void hb_threadInit( void ) /* nothing to do */ #elif defined( HB_CRITICAL_INIT ) HB_CRITICAL_INIT( s_critical_init ); + HB_CRITICAL_INIT( s_critical_once ); + HB_CRITICAL_INIT( s_critical_mtx ); #endif s_fThreadInit = TRUE; } @@ -157,10 +164,17 @@ void hb_threadExit( void ) if( s_fThreadInit ) { s_fThreadInit = FALSE; + if( s_pOnceMutex ) + { + hb_itemRelease( s_pOnceMutex ); + s_pOnceMutex = NULL; + } #if !defined( HB_MT_VM ) /* nothing to do */ #elif defined( HB_CRITICAL_DESTROY ) HB_CRITICAL_DESTROY( s_critical_init ); + HB_CRITICAL_DESTROY( s_critical_once ); + HB_CRITICAL_DESTROY( s_critical_mtx ); #endif } } @@ -761,6 +775,50 @@ HB_FUNC( HB_THREADTERMINATEALL ) #endif } +HB_FUNC( HB_THREADONCE ) +{ + PHB_ITEM pItem = hb_param( 1, HB_IT_ANY ); + if( pItem && ISBYREF( 1 ) ) + { + BOOL fFirstCall = FALSE; + if( HB_IS_NIL( pItem ) ) + { + PHB_ITEM pAction = hb_param( 2, HB_IT_BLOCK | HB_IT_SYMBOL ); + +#if defined( HB_MT_VM ) + if( !s_pOnceMutex ) + { + if( !s_fThreadInit ) + hb_threadInit(); + HB_CRITICAL_LOCK( s_critical_once ); + if( !s_pOnceMutex ) + s_pOnceMutex = hb_threadMutexCreate( FALSE ); + HB_CRITICAL_UNLOCK( s_critical_once ); + } + if( hb_threadMutexLock( s_pOnceMutex ) ) + { + if( HB_IS_NIL( pItem ) ) + { + hb_storl( TRUE, 1 ); + fFirstCall = TRUE; + if( pAction ) + hb_vmEvalBlock( pAction ); + } + hb_threadMutexUnlock( s_pOnceMutex ); + } +#else + hb_storl( TRUE, 1 ); + fFirstCall = TRUE; + if( pAction ) + hb_vmEvalBlock( pAction ); +#endif + } + hb_retl( fFirstCall ); + } + else + hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + /* II. MUTEXES */ typedef struct _HB_MUTEX @@ -819,7 +877,7 @@ static void hb_mutexUnlink( PHB_MUTEX *pList, PHB_MUTEX pItem ) #if defined( HB_MT_VM ) static void hb_mutexUnlockList( PHB_MUTEX * pList, PHB_MTXLST * pStore ) { - HB_CRITICAL_LOCK( s_critical_init ); + HB_CRITICAL_LOCK( s_critical_mtx ); if( *pList ) { PHB_MUTEX pMutex = *pList; @@ -848,7 +906,7 @@ static void hb_mutexUnlockList( PHB_MUTEX * pList, PHB_MTXLST * pStore ) } while( pMutex != *pList ); } - HB_CRITICAL_UNLOCK( s_critical_init ); + HB_CRITICAL_UNLOCK( s_critical_mtx ); } static void hb_mutexLockList( PHB_MTXLST pList ) @@ -894,9 +952,9 @@ static HB_GARBAGE_FUNC( hb_mutexDestructor ) PHB_MUTEX pMutex = ( PHB_MUTEX ) Cargo; #if defined( HB_MT_VM ) - HB_CRITICAL_LOCK( s_critical_init ); + HB_CRITICAL_LOCK( s_critical_mtx ); hb_mutexUnlink( pMutex->fSync ? &s_pSyncList : &s_pMutexList, pMutex ); - HB_CRITICAL_UNLOCK( s_critical_init ); + HB_CRITICAL_UNLOCK( s_critical_mtx ); #else hb_mutexUnlink( pMutex->fSync ? &s_pSyncList : &s_pMutexList, pMutex ); #endif @@ -953,9 +1011,9 @@ PHB_ITEM hb_threadMutexCreate( BOOL fSync ) pMutex->fSync = fSync; #if defined( HB_MT_VM ) - HB_CRITICAL_LOCK( s_critical_init ); + HB_CRITICAL_LOCK( s_critical_mtx ); hb_mutexLink( fSync ? &s_pSyncList : &s_pMutexList, pMutex ); - HB_CRITICAL_UNLOCK( s_critical_init ); + HB_CRITICAL_UNLOCK( s_critical_mtx ); #else hb_mutexLink( fSync ? &s_pSyncList : &s_pMutexList, pMutex ); #endif diff --git a/harbour/tests/speedtst.prg b/harbour/tests/speedtst.prg index 6decb5e12c..b711bdcab9 100644 --- a/harbour/tests/speedtst.prg +++ b/harbour/tests/speedtst.prg @@ -55,10 +55,11 @@ proc main( ... ) - local aParams, nMT, cExclude, lScale, cParam, lSyntax, i + local aParams, nMT, cExclude, lScale, cParam, cMemTests, lSyntax, i aParams := hb_aparams() lSyntax := lScale := .f. + cMemTests := "029 030 023 025 027 040 041 043 052 053 019 022 031 032 054 " cExclude := "" nMT := 0 for each cParam in aParams @@ -79,13 +80,16 @@ proc main( ... ) endif elseif cParam = "--exclude=" if substr( cParam, 11 ) == "mem" - cExclude += "029 030 023 025 027 040 041 043 052 053 019 022 031 032 " + cExclude += cMemTests else cExclude += strtran( strtran( strtran( substr( cParam, 11 ), ; ".", " " ), ".", " " ), "/", " " ) + " " endif elseif cParam = "--only=" cExclude := "" + if substr( cParam, 8 ) == "mem" + cParam := cMemTests + endif for i := 1 to N_TESTS if !strzero( i, 3 ) $ cParam cExclude += strzero( i, 3 ) + " " @@ -214,6 +218,30 @@ return #endif +/* initialize mutex in hb_trheadDoOnce() */ +init proc once_init() + hb_threadOnce() +return + +function hb_threadOnce( xOnceControl, bAction ) + static s_mutex + local lFirstCall := .f. + if s_mutex == NIL + s_mutex := hb_mutexCreate() + endif + if xOnceControl == NIL + hb_mutexLock( s_mutex ) + if xOnceControl == NIL + xOnceControl := .t. + lFirstCall := .t. + if bAction != NIL + eval( bAction ) + endif + endif + hb_mutexUnlock( s_mutex ) + endif +return lFirstCall + #endif @@ -389,30 +417,6 @@ TEST t053 CODE x := f5() TEST t054 WITH c := dtos( date() ) CODE f_prv( c ) -/* initialize mutex in hb_trheadDoOnce() */ -init proc once_init() - hb_threadOnce() -return - -function hb_threadOnce( xOnceControl, bAction ) - static s_mutex - local lFirstCall := .f. - if s_mutex == NIL - s_mutex := hb_mutexCreate() - endif - if xOnceControl == NIL - hb_mutexLock( s_mutex ) - if xOnceControl == NIL - xOnceControl := .t. - lFirstCall := .t. - if bAction != NIL - eval( bAction ) - endif - endif - hb_mutexUnlock( s_mutex ) - endif -return lFirstCall - function thTest( mtxJobs, aResults ) local xJob while .T.