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( @<item> <value> ) -> <lInitialized>
It assigns <value> to <item> if <item> 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
This commit is contained in:
@@ -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( @<item> <value> ) -> <lInitialized>
|
||||
It assigns <value> to <item> if <item> 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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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) )
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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( @<item> <value> ) -> <lInitialized>
|
||||
* assign <value> to @<item> only if <item> 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
|
||||
|
||||
Reference in New Issue
Block a user