diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 9adeb31ee4..e9780384d9 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,24 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-12-11 04:13 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapiitm.h + * harbour/src/vm/classes.c + * added new internal HVM macro + + * harbour/src/vm/thread.c + + added new function + hb_threadOnceInit( @ ) -> + It assigns to if is NIL in MT safe way so it's + assigned only once. It's reduced but faster version of hb_threadOnce() + + * harbour/include/hbapicdp.h + * define HB_WCHAR as wchar_t on Windows platforms for compilers which + refuse to make conversions between types using the same base type. + + * harbour/contrib/hbwin/win_dll.c + * code cleanup + 2009-12-11 00:20 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) + contrib/hbqt/hbqt_hbdbfmodel.h + Missed from prev commits. diff --git a/harbour/contrib/hbwin/win_dll.c b/harbour/contrib/hbwin/win_dll.c index a12c892713..07bcd177c9 100644 --- a/harbour/contrib/hbwin/win_dll.c +++ b/harbour/contrib/hbwin/win_dll.c @@ -66,7 +66,7 @@ #include "hbapiitm.h" #include "hbwinuni.h" -#if !defined( HB_NO_ASM ) && defined( HB_OS_WIN ) && !defined( __CYGWIN__ ) +#if defined( HB_OS_WIN ) && !defined( __CYGWIN__ ) && !defined( HB_NO_ASM ) /* ================================================================== * DynaCall support comments below @@ -378,16 +378,12 @@ RESULT DynaCall( int iFlags, LPVOID lpFunction, int nArgs, typedef struct _XPP_DLLEXEC { - DWORD dwType; /* type info */ HMODULE hDLL; /* Handle */ - char * cProc; /* function name */ - WORD wOrdinal; /* function ordinal */ + BOOL fFreeDLL; /* Free library handle on destroy? */ DWORD dwFlags; /* Calling Flags */ - LPVOID lpFunc; + LPVOID lpFunc; /* Function Address */ } XPP_DLLEXEC, * PXPP_DLLEXEC; -#define _DLLEXEC_SIGNATURE 0x45584543 - #define _DLLEXEC_MAXPARAM 15 /* Based originally on CallDLL() from What32 */ @@ -447,6 +443,7 @@ static void DllExec( int iFlags, int iRtype, LPVOID lpFunction, PXPP_DLLEXEC xec case HB_IT_LONG: case HB_IT_DATE: case HB_IT_LOGICAL: + /* TOFIX: HB_IT_LONG is 64 bit integer */ Parm[ iCnt ].nWidth = sizeof( DWORD ); Parm[ iCnt ].numargs.dwArg = ( DWORD ) hb_itemGetNL( pParam ); @@ -490,12 +487,11 @@ static void DllExec( int iFlags, int iRtype, LPVOID lpFunction, PXPP_DLLEXEC xec Parm[ iCnt ].dwFlags = DC_FLAG_ARGPTR; /* use the pointer */ break; + + case HB_IT_ARRAY: case HB_IT_HASH: case HB_IT_SYMBOL: - case HB_IT_ALIAS: - case HB_IT_MEMOFLAG: case HB_IT_BLOCK: - case HB_IT_MEMVAR: default: hb_errRT_BASE( EG_ARG, 2010, "Unknown parameter type to DLL function", HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); @@ -612,20 +608,14 @@ static void DllExec( int iFlags, int iRtype, LPVOID lpFunction, PXPP_DLLEXEC xec /* ------------------------------------------------------------------ */ -#if !defined( HB_OS_WIN_CE ) static HB_GARBAGE_FUNC( _DLLUnload ) { PXPP_DLLEXEC xec = ( PXPP_DLLEXEC ) Cargo; - if( xec->dwType == _DLLEXEC_SIGNATURE ) + if( xec->hDLL && xec->fFreeDLL ) { - if( xec->hDLL ) - FreeLibrary( xec->hDLL ); - - if( xec->cProc ) - hb_xfree( xec->cProc ); - - xec->dwType = 0; + FreeLibrary( xec->hDLL ); + xec->hDLL = NULL; } } @@ -636,17 +626,29 @@ static const HB_GC_FUNCS s_gcDllFuncs = }; -#endif - -static LPVOID hb_getprocaddress( HMODULE hDLL, int iProc ) +static LPVOID hb_getprocaddress( HMODULE hDLL, int iParam ) { #if defined( HB_OS_WIN_CE ) - HB_SYMBOL_UNUSED( hDLL ); - HB_SYMBOL_UNUSED( iProc ); - return NULL; + void * hStr; + ULONG ulLen; + LPCWSTR szProc = hb_parstr_u16( iParam, HB_CDP_ENDIAN_NATIVE, &hStr, &ulLen ); + LPVOID lpFunction = ( LPVOID ) GetProcAddress( hDLL, szProc ? szProc : + ( LPCWSTR ) ( HB_PTRDIFF ) ( hb_parni( iParam ) & 0x0FFFF ) ); + + if( ! lpFunction && szProc ) /* try with WIDE suffix? */ + { + LPWSTR pszProcW = ( LPWSTR ) hb_xgrab( ( ulLen + 2 ) * sizeof( WCHAR ) ); + memcpy( pszProcW, szProc, ulLen * sizeof( WCHAR ) ); + pszProcW[ ulLen++ ] = L'W'; + pszProcW[ ulLen++ ] = 0; + lpFunction = ( LPVOID ) GetProcAddress( hDLL, pszProcW ); + hb_xfree( pszProcW ); + } + hb_strfree( hStr ); #else - const char * szProc = hb_parc( iProc ); - LPVOID lpFunction = ( LPVOID ) GetProcAddress( hDLL, szProc ? szProc : ( LPCSTR ) ( HB_PTRDIFF ) hb_parnint( iProc ) ); + const char * szProc = hb_parc( iParam ); + LPVOID lpFunction = ( LPVOID ) GetProcAddress( hDLL, szProc ? szProc : + ( LPCSTR ) ( HB_PTRDIFF ) ( hb_parni( iParam ) & 0x0FFFF ) ); if( ! lpFunction && szProc ) /* try with ANSI suffix? */ { @@ -654,16 +656,15 @@ static LPVOID hb_getprocaddress( HMODULE hDLL, int iProc ) lpFunction = ( LPVOID ) GetProcAddress( hDLL, pszFuncName ); hb_xfree( pszFuncName ); } - - return lpFunction; #endif + return lpFunction; } HB_FUNC( LOADLIBRARY ) { void * hName; - hb_retnint( ( HB_PTRDIFF ) LoadLibrary( ( LPCTSTR ) HB_PARSTRDEF( 1, &hName, NULL ) ) ); + hb_retnint( ( HB_PTRDIFF ) LoadLibrary( HB_PARSTRDEF( 1, &hName, NULL ) ) ); hb_strfree( hName ); } @@ -687,7 +688,7 @@ HB_FUNC( GETPROCADDRESS ) else hDLL = ( HMODULE ) hb_parptr( 1 ); - hb_retptr( hDLL ? ( void * ) hb_getprocaddress( hDLL, 2 ) : NULL ); + hb_retptr( hDLL ? hb_getprocaddress( hDLL, 2 ) : NULL ); } #ifdef HB_COMPAT_XPP @@ -704,16 +705,16 @@ HB_FUNC( DLLUNLOAD ) HB_FUNC( DLLCALL ) { - HMODULE hDLL; + HMODULE hDLL = NULL; if( HB_ISPOINTER( 1 ) ) hDLL = ( HMODULE ) hb_parptr( 1 ); else if( HB_ISNUM( 1 ) ) hDLL = ( HMODULE ) ( HB_PTRDIFF ) hb_parnint( 1 ); - else + else if( HB_ISCHAR( 1 ) ) { void * hName; - hDLL = LoadLibrary( ( LPCTSTR ) HB_PARSTRDEF( 1, &hName, NULL ) ); + hDLL = LoadLibrary( HB_PARSTR( 1, &hName, NULL ) ); hb_strfree( hName ); } @@ -730,17 +731,18 @@ HB_FUNC( DLLCALL ) HB_FUNC( DLLPREPARECALL ) { -#if ! defined( HB_OS_WIN_CE ) PXPP_DLLEXEC xec = ( PXPP_DLLEXEC ) hb_gcAllocate( sizeof( XPP_DLLEXEC ), &s_gcDllFuncs ); - char * pszErrorText; + const char * pszErrorText; memset( xec, 0, sizeof( XPP_DLLEXEC ) ); if( HB_ISCHAR( 1 ) ) { void * hName; - xec->hDLL = LoadLibrary( ( LPCTSTR ) HB_PARSTRDEF( 1, &hName, NULL ) ); + xec->hDLL = LoadLibrary( HB_PARSTR( 1, &hName, NULL ) ); hb_strfree( hName ); + if( xec->hDLL ) + xec->fFreeDLL = TRUE; } else if( HB_ISPOINTER( 1 ) ) xec->hDLL = ( HMODULE ) hb_parptr( 1 ); @@ -749,53 +751,32 @@ HB_FUNC( DLLPREPARECALL ) if( xec->hDLL ) { - HB_SIZE ulLen = 0; - - if( HB_ISCHAR( 3 ) ) - { - ulLen = hb_parclen( 3 ) + 1; - xec->cProc = ( char * ) hb_xgrab( ulLen + 1 ); /* Reserving space for possible ANSI "A" suffix. */ - hb_strncpy( xec->cProc, hb_parc( 3 ), ulLen ); - } - else if( HB_ISNUM( 3 ) ) - xec->wOrdinal = ( WORD ) hb_parni( 3 ); - - xec->lpFunc = ( LPVOID ) GetProcAddress( xec->hDLL, xec->cProc ? xec->cProc : ( LPCSTR ) ( HB_PTRDIFF ) xec->wOrdinal ); - - if( ! xec->lpFunc && xec->cProc ) /* try with ANSI suffix? */ - xec->lpFunc = ( LPVOID ) GetProcAddress( xec->hDLL, hb_strncat( xec->cProc, "A", ulLen ) ); - + xec->lpFunc = hb_getprocaddress( xec->hDLL, 3 ); if( xec->lpFunc ) { - xec->dwType = _DLLEXEC_SIGNATURE; xec->dwFlags = HB_ISNUM( 2 ) ? hb_parnl( 2 ) : DC_CALL_STD; hb_retptrGC( xec ); return; } - - if( HB_ISCHAR( 1 ) ) - FreeLibrary( xec->hDLL ); - - pszErrorText = HB_ISCHAR( 3 ) ? ( char * ) "Invalid function name" : ( char * ) "Invalid function ordinal"; + pszErrorText = HB_ISCHAR( 3 ) ? "Invalid function name" : "Invalid function ordinal"; } else - pszErrorText = HB_ISCHAR( 1 ) ? ( char * ) "Invalid library name" : ( char * ) "Invalid library handle"; + pszErrorText = HB_ISCHAR( 1 ) ? "Invalid library name" : "Invalid library handle"; hb_gcFree( xec ); hb_errRT_BASE( EG_ARG, 2010, pszErrorText, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); -#endif } HB_FUNC( DLLEXECUTECALL ) { - PXPP_DLLEXEC xec = ( PXPP_DLLEXEC ) hb_parptr( 1 ); + PXPP_DLLEXEC xec = ( PXPP_DLLEXEC ) hb_parptrGC( &s_gcDllFuncs, 1 ); - if( xec && xec->dwType == _DLLEXEC_SIGNATURE && xec->hDLL && xec->lpFunc ) + if( xec && xec->hDLL && xec->lpFunc ) DllExec( 0, 0, NULL, xec, hb_pcount(), 2 ); } -#endif +#endif /* HB_COMPAT_XPP */ /* ------------------------------------------------------------------ */ @@ -816,4 +797,4 @@ HB_FUNC( CALLDLLTYPED ) DllExec( DC_CALL_STD, hb_parni( 2 ), ( LPVOID ) hb_parptr( 1 ), NULL, hb_pcount(), 3 ); } -#endif +#endif /* HB_OS_WIN && && !__CYGWIN__ !HB_NO_ASM */ diff --git a/harbour/include/hbapicdp.h b/harbour/include/hbapicdp.h index a7838c4efa..c5fdf00032 100644 --- a/harbour/include/hbapicdp.h +++ b/harbour/include/hbapicdp.h @@ -74,7 +74,11 @@ HB_EXTERN_BEGIN hb_cdpRegister( &s_codepage ); \ HB_CALL_ON_STARTUP_END( hb_codepage_Init_##id ) -typedef USHORT HB_WCHAR; +#if defined( HB_OS_WIN ) + typedef wchar_t HB_WCHAR; +#else + typedef unsigned short HB_WCHAR; +#endif typedef struct _HB_UNITABLE { diff --git a/harbour/include/hbapiitm.h b/harbour/include/hbapiitm.h index f3ded23b63..6647b70fbb 100644 --- a/harbour/include/hbapiitm.h +++ b/harbour/include/hbapiitm.h @@ -202,6 +202,18 @@ extern HB_EXPORT PHB_ITEM hb_itemDeserialize( const char ** pBufferPtr, ULON # define hb_itemRawMove( dst, src ) hb_itemMove( (dst), (src) ) #endif + /* intentional low level hack to eliminate race condition in + * unprotected readonly access in few places in core code only. + * hb_item[Raw]Move() moves HB_ITEM structure members first coping + * 'type' and then 'item' parts of HB_ITEM. In this macro the order + * is reverted. [druzus] + */ +# define hb_itemSafeMove( dst, src ) do { \ + (dst)->item = (src)->item; \ + (dst)->type = (src)->type; \ + (src)->type = HB_IT_NIL; \ + } while( 0 ) + #else # define hb_itemSetNil( item ) hb_itemClear( (item) ) diff --git a/harbour/src/vm/classes.c b/harbour/src/vm/classes.c index e7cdb61373..b2c7e4951f 100644 --- a/harbour/src/vm/classes.c +++ b/harbour/src/vm/classes.c @@ -4970,16 +4970,10 @@ HB_FUNC( __CLSUNLOCKDEF ) if( pClsDst && pClsSrc && HB_IS_NIL( pClsDst ) && ! HB_ISBYREF( 2 ) ) { - /* intentional low level hack to eliminate race condition in - * unprotected readonly access. - * hb_itemMove() uses memcpy() for whole HB_ITEM structure first - * coping 'type' and then 'item' parts of HB_ITEM so it cannot be - * used by us. [druzus] + /* special core code only macro used to eliminate race condition + * in unprotected readonly access to pClsDst variable. */ - memcpy( &pClsDst->item, &pClsSrc->item, sizeof( pClsDst->item ) ); - /* pClsDst->item.asArray.value = pClsSrc->item.asArray.value; */ - pClsDst->type = pClsSrc->type; - pClsSrc->type = HB_IT_NIL; + hb_itemSafeMove( pClsDst, pClsSrc ); } if( s_pClassMtx ) diff --git a/harbour/src/vm/thread.c b/harbour/src/vm/thread.c index a7c114e3bf..81f5349289 100644 --- a/harbour/src/vm/thread.c +++ b/harbour/src/vm/thread.c @@ -1494,6 +1494,44 @@ HB_FUNC( HB_THREADONCE ) hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); } +/* hb_threadOnceInit( @ ) -> + * assign to @ only if is NIL + */ +HB_FUNC( HB_THREADONCEINIT ) +{ + PHB_ITEM pItem = hb_param( 1, HB_IT_ANY ); + PHB_ITEM pValue = hb_param( 1, HB_IT_ANY ); + + if( pItem && pValue && HB_ISBYREF( 1 ) && !HB_ISBYREF( 2 ) ) + { + BOOL fInitialized = FALSE; + + if( HB_IS_NIL( pItem ) && !HB_IS_NIL( pValue ) ) + { +#if defined( HB_MT_VM ) + if( !s_fThreadInit ) + hb_threadInit(); + HB_CRITICAL_LOCK( s_once_mtx ); + if( HB_IS_NIL( pItem ) ) + { + /* special core code only macro used to eliminate race condition + * in unprotected readonly access to pItem variable. + */ + hb_itemSafeMove( pItem, pValue ); + fInitialized = TRUE; + } + HB_CRITICAL_UNLOCK( s_once_mtx ); +#else + hb_itemSafeMove( pItem, pValue ); + fInitialized = TRUE; +#endif + } + hb_retl( fInitialized ); + } + else + hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + /* II. MUTEXES */ typedef struct _HB_MUTEX