2009-06-05 06:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbclass.ch
+ extended support for xbase++ compatible method declaration:
[SYNC] METHOD <methodName1>[([<params>])] ;
[ , <methodNameN>[([<params>])] ]
* harbour/include/hbthread.h
* harbour/source/vm/thread.c
* harbour/source/vm/classes.c
+ added alternative support for SYNC method which does not use
sync mutexes. The old method is still present. I'll remove it
when xbase++ users confirm that the new one exactly emulates
xbase++ behavior.
* harbour/source/vm/classes.c
* harbour/source/rtl/tthreadx.prg
* switch to alternative SYNC method implementation which seems to be
xbase++ compatible - please test
! fixed missing thread interrupt in recent modification for ::setInterval
This commit is contained in:
@@ -17,6 +17,26 @@
|
||||
past entries belonging to these authors: Viktor Szakats.
|
||||
*/
|
||||
|
||||
2009-06-05 06:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/include/hbclass.ch
|
||||
+ extended support for xbase++ compatible method declaration:
|
||||
[SYNC] METHOD <methodName1>[([<params>])] ;
|
||||
[ , <methodNameN>[([<params>])] ]
|
||||
|
||||
* harbour/include/hbthread.h
|
||||
* harbour/source/vm/thread.c
|
||||
* harbour/source/vm/classes.c
|
||||
+ added alternative support for SYNC method which does not use
|
||||
sync mutexes. The old method is still present. I'll remove it
|
||||
when xbase++ users confirm that the new one exactly emulates
|
||||
xbase++ behavior.
|
||||
|
||||
* harbour/source/vm/classes.c
|
||||
* harbour/source/rtl/tthreadx.prg
|
||||
* switch to alternative SYNC method implementation which seems to be
|
||||
xbase++ compatible - please test
|
||||
! fixed missing thread interrupt in recent modification for ::setInterval
|
||||
|
||||
2009-06-04 23:00 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
|
||||
* utils/hbmk2/hbmk2.prg
|
||||
+ Added support for hbcs= lins in .hbc files. This means
|
||||
|
||||
@@ -571,8 +571,10 @@ DECLARE HBClass ;
|
||||
#xcommand SYNC METHOD <MethodName> [<decl,...>] => METHOD <MethodName> [<decl>] SYNC
|
||||
#xcommand SYNC CLASS METHOD <MethodName> [<decl,...>] => CLASSMETHOD <MethodName> [<decl>] SYNC
|
||||
|
||||
#xcommand METHOD <!MethodName1!>, <!MethodName2!> [, <!MethodNameN!>] => ;
|
||||
#xcommand METHOD <!MethodName1!>[([<params,...>])], <!MethodName2!>[([<params,...>])] [, <!MethodNameN!>[([<params,...>])]] => ;
|
||||
METHOD <MethodName1> [ ; METHOD <MethodName2> ] [ ; METHOD <MethodNameN> ]
|
||||
#xcommand SYNC METHOD <!MethodName1!>[([<params,...>])], <!MethodName2!>[([<params,...>])] [, <!MethodNameN!>[([<params,...>])]] => ;
|
||||
SYNC METHOD <MethodName1> [ ; SYNC METHOD <MethodName2> ] [ ; SYNC METHOD <MethodNameN> ]
|
||||
|
||||
#xcommand METHOD <!className!>:<!methodName!>[([<params,...>])] => ;
|
||||
METHOD <methodName>( <params> ) CLASS <className>
|
||||
|
||||
@@ -340,6 +340,8 @@ extern PHB_ITEM hb_threadMutexTimedSubscribe( PHB_ITEM pItem, ULONG ulMilliSec,
|
||||
#if defined( HB_MT_VM ) && defined( _HB_API_INTERNAL_ )
|
||||
|
||||
extern void hb_threadMutexUnlockAll( void );
|
||||
extern void hb_threadMutexSyncSignal( PHB_ITEM pItemMtx );
|
||||
extern BOOL hb_threadMutexSyncWait( PHB_ITEM pItemMtx, ULONG ulMilliSec, PHB_ITEM pItemSync );
|
||||
|
||||
#if defined( HB_NO_TLS )
|
||||
# undef HB_USE_TLS
|
||||
|
||||
@@ -86,15 +86,10 @@ METHOD new( ... ) CLASS TSIGNAL
|
||||
RETURN Self
|
||||
|
||||
METHOD wait( nTimeOut ) CLASS TSIGNAL
|
||||
/* TOCHECK: I do not know if strict Xbase++ compatibility needs
|
||||
* hb_mutexSubscribe() or hb_mutexSubscribeNow()
|
||||
* Please change it if necessary
|
||||
*/
|
||||
RETURN hb_mutexSubscribe( ::mutex, ;
|
||||
iif( ISNUMBER( nTimeOut ), nTimeOut / 100, ) )
|
||||
RETURN __ClsSyncWait( ::mutex, nTimeOut )
|
||||
|
||||
METHOD signal() CLASS TSIGNAL
|
||||
hb_mutexNotify( ::mutex )
|
||||
__ClsSyncSignal( ::mutex )
|
||||
RETURN Self
|
||||
|
||||
|
||||
@@ -105,22 +100,22 @@ METHOD signal() CLASS TSIGNAL
|
||||
CREATE CLASS TThread FUNCTION Thread
|
||||
|
||||
EXPORTED:
|
||||
VAR cargo AS USUAL SYNC
|
||||
VAR cargo AS USUAL
|
||||
VAR active AS LOGICAL READONLY INIT .f.
|
||||
VAR deltaTime AS NUMERIC READONLY INIT 0
|
||||
VAR interval AS USUAL READONLY INIT NIL
|
||||
VAR priority AS NUMERIC READONLY INIT 0
|
||||
VAR startCount AS NUMERIC READONLY INIT 0
|
||||
VAR startTime AS USUAL READONLY INIT NIL
|
||||
VAR atEnd AS USUAL INIT NIL SYNC
|
||||
VAR atStart AS USUAL INIT NIL SYNC
|
||||
VAR result AS USUAL INIT NIL SYNC
|
||||
VAR atEnd AS USUAL INIT NIL
|
||||
VAR atStart AS USUAL INIT NIL
|
||||
VAR result AS USUAL INIT NIL
|
||||
|
||||
PROTECTED:
|
||||
VAR maxStackSize AS USUAL INIT 50000
|
||||
|
||||
HIDDEN:
|
||||
VAR pThreadID AS USUAL INIT NIL SYNC
|
||||
VAR pThreadID AS USUAL INIT NIL
|
||||
|
||||
EXPORTED:
|
||||
METHOD new()
|
||||
@@ -131,11 +126,11 @@ PROTECTED:
|
||||
METHOD execute()
|
||||
|
||||
EXPORTED:
|
||||
METHOD quit( xResult, nRestart ) SYNC
|
||||
METHOD quit( xResult, nRestart )
|
||||
METHOD setInterval( nHSeconds )
|
||||
METHOD setPriority( nPriority )
|
||||
METHOD setStartTime( nSeconds )
|
||||
METHOD start() SYNC
|
||||
METHOD start()
|
||||
METHOD synchronize( nTimeOut )
|
||||
METHOD threadSelf()
|
||||
METHOD threadID()
|
||||
@@ -179,7 +174,7 @@ METHOD quit( xResult, nRestart ) CLASS TTHREAD
|
||||
RETURN NIL
|
||||
|
||||
METHOD setInterval( nHSeconds ) CLASS TTHREAD
|
||||
IF ISNUMBER( nHSeconds )
|
||||
IF nHSeconds == NIL .OR. ISNUMBER( nHSeconds )
|
||||
::interval := nHSeconds
|
||||
ENDIF
|
||||
RETURN .F.
|
||||
@@ -212,11 +207,12 @@ METHOD start( xAction, ... ) CLASS TTHREAD
|
||||
::startTime := Seconds()
|
||||
ThreadObject( Self )
|
||||
::result := ::execute( ... )
|
||||
::startTime := NIL
|
||||
IF ISNUMBER( ::interval )
|
||||
hb_idleSleep( ::interval / 100 )
|
||||
LOOP
|
||||
ENDIF
|
||||
::startTime := NIL
|
||||
EXIT
|
||||
ENDDO
|
||||
RETURN NIL
|
||||
}, ... )
|
||||
@@ -239,6 +235,7 @@ METHOD start( xAction, ... ) CLASS TTHREAD
|
||||
hb_idleSleep( ::interval / 100 )
|
||||
LOOP
|
||||
ENDIF
|
||||
EXIT
|
||||
ENDDO
|
||||
RETURN NIL
|
||||
}, ... )
|
||||
|
||||
@@ -926,7 +926,7 @@ static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc )
|
||||
pClsDst->uiMutexOffset = pClsSrc->uiMutexOffset;
|
||||
pClsDst->ulOpFlags = pClsSrc->ulOpFlags;
|
||||
if( pClsSrc->pMutex )
|
||||
pClsDst->pMutex = hb_threadMutexCreate( TRUE );
|
||||
pClsDst->pMutex = hb_threadMutexCreate( FALSE );
|
||||
|
||||
if( pClsSrc->uiInitDatas )
|
||||
{
|
||||
@@ -2991,7 +2991,7 @@ static BOOL hb_clsAddMsg( USHORT uiClass, const char * szMessage,
|
||||
if( uiScope & HB_OO_CLSTP_CLASS )
|
||||
{
|
||||
if( !pClass->pMutex )
|
||||
pClass->pMutex = hb_threadMutexCreate( TRUE );
|
||||
pClass->pMutex = hb_threadMutexCreate( FALSE );
|
||||
pNewMeth->pFuncSym = &s___msgSyncClass;
|
||||
}
|
||||
else
|
||||
@@ -3353,7 +3353,7 @@ static USHORT hb_clsNew( const char * szClassName, USHORT uiDatas,
|
||||
if( pNewCls->uiMutexOffset )
|
||||
pNewCls->uiMutexOffset = pNewCls->uiDatas + 1;
|
||||
if( fClsMutex && !pNewCls->pMutex )
|
||||
pNewCls->pMutex = hb_threadMutexCreate( TRUE );
|
||||
pNewCls->pMutex = hb_threadMutexCreate( FALSE );
|
||||
|
||||
return s_uiClasses;
|
||||
}
|
||||
@@ -3479,7 +3479,7 @@ static PHB_ITEM hb_clsInst( USHORT uiClass )
|
||||
|
||||
if( pClass->uiMutexOffset )
|
||||
{
|
||||
PHB_ITEM pMutex = hb_threadMutexCreate( TRUE );
|
||||
PHB_ITEM pMutex = hb_threadMutexCreate( FALSE );
|
||||
hb_arraySet( pSelf, pClass->uiMutexOffset, pMutex );
|
||||
hb_itemRelease( pMutex );
|
||||
}
|
||||
@@ -4090,6 +4090,60 @@ HB_FUNC( __SENDER )
|
||||
}
|
||||
}
|
||||
|
||||
HB_FUNC( __CLSSYNCSIGNAL )
|
||||
{
|
||||
#if defined( HB_MT_VM )
|
||||
hb_threadMutexSyncSignal( hb_param( 1, HB_IT_ANY ) );
|
||||
#endif /* HB_MT_VM */
|
||||
}
|
||||
|
||||
HB_FUNC( __CLSSYNCWAIT )
|
||||
{
|
||||
#if defined( HB_MT_VM )
|
||||
HB_STACK_TLS_PRELOAD
|
||||
PHB_ITEM pMutex = NULL;
|
||||
ULONG ulMilliSec = HB_THREAD_INFINITE_WAIT;
|
||||
LONG lOffset = hb_stackBaseProcOffset( 2 );
|
||||
|
||||
if( lOffset > 0 )
|
||||
{
|
||||
PHB_ITEM pBase = hb_stackItem( lOffset );
|
||||
PHB_STACK_STATE pStack = pBase->item.asSymbol.stackstate;
|
||||
USHORT uiClass = pStack->uiClass;
|
||||
|
||||
if( uiClass && uiClass <= s_uiClasses )
|
||||
{
|
||||
PCLASS pClass = s_pClasses[ uiClass ];
|
||||
PMETHOD pMethod = pClass->pMethods + pStack->uiMethod;
|
||||
|
||||
if( pMethod->pFuncSym == &s___msgSync )
|
||||
{
|
||||
PHB_ITEM pSelf = hb_stackItem( lOffset + 1 );
|
||||
|
||||
/* Is it inline method? */
|
||||
if( HB_IS_BLOCK( pSelf ) && pBase->item.asSymbol.value == &hb_symEval )
|
||||
pSelf = hb_stackItem( pBase->item.asSymbol.stackstate->lBaseItem + 1 );
|
||||
|
||||
uiClass = hb_objGetClass( pSelf );
|
||||
if( uiClass && uiClass <= s_uiClasses )
|
||||
pMutex = hb_arrayGetItemPtr( pSelf, s_pClasses[ uiClass ]->uiMutexOffset );
|
||||
}
|
||||
else if( pMethod->pFuncSym == &s___msgSyncClass )
|
||||
pMutex = pClass->pMutex;
|
||||
}
|
||||
}
|
||||
|
||||
if( ISNUM( 2 ) )
|
||||
{
|
||||
double dTimeOut = hb_parnd( 2 );
|
||||
if( dTimeOut > 0 )
|
||||
ulMilliSec = ( ULONG ) ( dTimeOut * 10 );
|
||||
}
|
||||
|
||||
hb_retl( hb_threadMutexSyncWait( hb_param( 1, HB_IT_ANY ), ulMilliSec, pMutex ) );
|
||||
#endif /* HB_MT_VM */
|
||||
}
|
||||
|
||||
/*
|
||||
* ClassH( <obj> ) -> <hClass>
|
||||
*
|
||||
@@ -4136,32 +4190,37 @@ static HARBOUR hb___msgClassName( void )
|
||||
|
||||
static int hb_methodType( PMETHOD pMethod )
|
||||
{
|
||||
if ( pMethod->pFuncSym == &s___msgSetClsData ||
|
||||
pMethod->pFuncSym == &s___msgGetClsData ||
|
||||
pMethod->pFuncSym == &s___msgSetShrData ||
|
||||
pMethod->pFuncSym == &s___msgGetShrData )
|
||||
PHB_SYMB pFuncSym = pMethod->pFuncSym;
|
||||
|
||||
if( pFuncSym == &s___msgSync || pFuncSym == &s___msgSyncClass )
|
||||
pFuncSym = pMethod->pRealSym;
|
||||
|
||||
if ( pFuncSym == &s___msgSetClsData ||
|
||||
pFuncSym == &s___msgGetClsData ||
|
||||
pFuncSym == &s___msgSetShrData ||
|
||||
pFuncSym == &s___msgGetShrData )
|
||||
return HB_OO_MSG_CLASSDATA;
|
||||
|
||||
else if( pMethod->pFuncSym == &s___msgSetData ||
|
||||
pMethod->pFuncSym == &s___msgGetData )
|
||||
else if( pFuncSym == &s___msgSetData ||
|
||||
pFuncSym == &s___msgGetData )
|
||||
return HB_OO_MSG_DATA;
|
||||
|
||||
else if( pMethod->pFuncSym == &s___msgEvalInline )
|
||||
else if( pFuncSym == &s___msgEvalInline )
|
||||
return HB_OO_MSG_INLINE;
|
||||
|
||||
else if( pMethod->pFuncSym == &s___msgVirtual )
|
||||
else if( pFuncSym == &s___msgVirtual )
|
||||
return HB_OO_MSG_VIRTUAL;
|
||||
|
||||
else if( pMethod->pFuncSym == &s___msgSuper )
|
||||
else if( pFuncSym == &s___msgSuper )
|
||||
return HB_OO_MSG_SUPER;
|
||||
|
||||
else if( pMethod->pFuncSym == &s___msgRealClass )
|
||||
else if( pFuncSym == &s___msgRealClass )
|
||||
return HB_OO_MSG_REALCLASS;
|
||||
|
||||
else if( pMethod->pFuncSym == &s___msgDelegate )
|
||||
else if( pFuncSym == &s___msgDelegate )
|
||||
return HB_OO_MSG_DELEGATE;
|
||||
|
||||
else if( pMethod->pFuncSym == &s___msgPerform )
|
||||
else if( pFuncSym == &s___msgPerform )
|
||||
return HB_OO_MSG_PERFORM;
|
||||
|
||||
else if( pMethod->pMessage == s___msgOnError.pDynSym )
|
||||
@@ -4204,22 +4263,9 @@ static HARBOUR hb___msgClassSel( void )
|
||||
{
|
||||
if( ( nParam == HB_MSGLISTALL ) ||
|
||||
( nParam == HB_MSGLISTCLASS &&
|
||||
(
|
||||
( pMethod->pFuncSym == &s___msgSetClsData ) ||
|
||||
( pMethod->pFuncSym == &s___msgGetClsData ) ||
|
||||
( pMethod->pFuncSym == &s___msgSetShrData ) ||
|
||||
( pMethod->pFuncSym == &s___msgGetShrData )
|
||||
)
|
||||
) ||
|
||||
hb_methodType( pMethod ) == HB_OO_MSG_CLASSDATA ) ||
|
||||
( nParam == HB_MSGLISTPURE &&
|
||||
!(
|
||||
( pMethod->pFuncSym == &s___msgSetClsData ) ||
|
||||
( pMethod->pFuncSym == &s___msgGetClsData ) ||
|
||||
( pMethod->pFuncSym == &s___msgSetShrData ) ||
|
||||
( pMethod->pFuncSym == &s___msgGetShrData )
|
||||
)
|
||||
)
|
||||
)
|
||||
hb_methodType( pMethod ) != HB_OO_MSG_CLASSDATA ) )
|
||||
{
|
||||
if( nScope == 0 || ( pMethod->uiScope & nScope ) != 0 )
|
||||
{
|
||||
|
||||
@@ -1549,6 +1549,173 @@ PHB_ITEM hb_threadMutexCreate( BOOL fSync )
|
||||
return pItem;
|
||||
}
|
||||
|
||||
#if defined( HB_MT_VM )
|
||||
void hb_threadMutexSyncSignal( PHB_ITEM pItemMtx )
|
||||
{
|
||||
PHB_MUTEX pMutex = hb_mutexPtr( pItemMtx );
|
||||
|
||||
if( pMutex )
|
||||
{
|
||||
HB_CRITICAL_LOCK( pMutex->mutex );
|
||||
|
||||
if( pMutex->waiters )
|
||||
{
|
||||
int iCount = pMutex->waiters;
|
||||
ULONG ulLen;
|
||||
|
||||
if( pMutex->events )
|
||||
{
|
||||
ulLen = hb_arrayLen( pMutex->events );
|
||||
iCount -= ulLen;
|
||||
if( iCount > 0 )
|
||||
hb_arraySize( pMutex->events, ulLen + iCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
ulLen = 0;
|
||||
pMutex->events = hb_itemArrayNew( iCount );
|
||||
}
|
||||
if( iCount == 1 )
|
||||
HB_COND_SIGNAL( pMutex->cond_w );
|
||||
else if( iCount > 0 )
|
||||
HB_COND_SIGNALN( pMutex->cond_w, iCount );
|
||||
}
|
||||
else if( !pMutex->events )
|
||||
pMutex->events = hb_itemArrayNew( 1 );
|
||||
|
||||
HB_CRITICAL_UNLOCK( pMutex->mutex );
|
||||
}
|
||||
}
|
||||
|
||||
BOOL hb_threadMutexSyncWait( PHB_ITEM pItemMtx, ULONG ulMilliSec,
|
||||
PHB_ITEM pItemSync )
|
||||
{
|
||||
PHB_MUTEX pMutex = hb_mutexPtr( pItemMtx ), pSyncMutex = NULL;
|
||||
BOOL fResult = FALSE;
|
||||
|
||||
if( pMutex )
|
||||
{
|
||||
if( pItemSync )
|
||||
{
|
||||
pSyncMutex = hb_mutexPtr( pItemSync );
|
||||
if( !pSyncMutex )
|
||||
pMutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( pMutex )
|
||||
{
|
||||
int lock_count = 0;
|
||||
|
||||
hb_vmUnlock();
|
||||
|
||||
HB_CRITICAL_LOCK( pMutex->mutex );
|
||||
|
||||
if( ulMilliSec && !( pMutex->events && hb_arrayLen( pMutex->events ) > 0 ) )
|
||||
{
|
||||
/* release own locks from sync mutex */
|
||||
if( pSyncMutex && HB_THREAD_EQUAL( pSyncMutex->owner, HB_THREAD_SELF() ) )
|
||||
{
|
||||
HB_CRITICAL_LOCK( pSyncMutex->mutex );
|
||||
lock_count = pSyncMutex->lock_count;
|
||||
pSyncMutex->lock_count = 0;
|
||||
pSyncMutex->owner = ( HB_THREAD_ID ) 0;
|
||||
if( pSyncMutex->lockers )
|
||||
HB_COND_SIGNAL( pSyncMutex->cond_l );
|
||||
HB_CRITICAL_UNLOCK( pSyncMutex->mutex );
|
||||
}
|
||||
|
||||
if( ulMilliSec == HB_THREAD_INFINITE_WAIT )
|
||||
{
|
||||
while( !pMutex->events || hb_arrayLen( pMutex->events ) == 0 )
|
||||
{
|
||||
pMutex->waiters++;
|
||||
# if defined( HB_PTHREAD_API )
|
||||
pthread_cond_wait( &pMutex->cond_w, &pMutex->mutex );
|
||||
# elif defined( HB_COND_HARBOUR_SUPPORT )
|
||||
_hb_thread_cond_wait( &pMutex->cond_w, &pMutex->mutex, HB_THREAD_INFINITE_WAIT );
|
||||
# else
|
||||
HB_CRITICAL_UNLOCK( pMutex->mutex );
|
||||
( void ) HB_COND_WAIT( pMutex->cond_w );
|
||||
HB_CRITICAL_LOCK( pMutex->mutex );
|
||||
# endif
|
||||
pMutex->waiters--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pMutex->waiters++;
|
||||
# if defined( HB_PTHREAD_API )
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
hb_threadTimeInit( &ts, ulMilliSec );
|
||||
while( !pMutex->events || hb_arrayLen( pMutex->events ) == 0 )
|
||||
{
|
||||
if( pthread_cond_timedwait( &pMutex->cond_w, &pMutex->mutex, &ts ) != 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
# else
|
||||
{
|
||||
/* TODO: on some platforms HB_COND_SIGNAL() may wake up more then
|
||||
* one thread so we should use while loop to check if wait
|
||||
* condition is true.
|
||||
*/
|
||||
# if defined( HB_COND_HARBOUR_SUPPORT )
|
||||
_hb_thread_cond_wait( &pMutex->cond_w, &pMutex->mutex, ulMilliSec );
|
||||
# else
|
||||
HB_CRITICAL_UNLOCK( pMutex->mutex );
|
||||
( void ) HB_COND_TIMEDWAIT( pMutex->cond_w, ulMilliSec );
|
||||
HB_CRITICAL_LOCK( pMutex->mutex );
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
pMutex->waiters--;
|
||||
}
|
||||
}
|
||||
|
||||
if( pMutex->events && hb_arrayLen( pMutex->events ) > 0 )
|
||||
{
|
||||
hb_arraySize( pMutex->events, hb_arrayLen( pMutex->events ) - 1 );
|
||||
fResult = TRUE;
|
||||
}
|
||||
|
||||
HB_CRITICAL_UNLOCK( pMutex->mutex );
|
||||
|
||||
/* restore the own locks on sync mutex if necessary */
|
||||
if( lock_count )
|
||||
{
|
||||
HB_CRITICAL_LOCK( pSyncMutex->mutex );
|
||||
if( pSyncMutex->owner )
|
||||
{
|
||||
pSyncMutex->lockers++;
|
||||
while( pSyncMutex->lock_count != 0 )
|
||||
{
|
||||
# if defined( HB_PTHREAD_API )
|
||||
pthread_cond_wait( &pSyncMutex->cond_l, &pSyncMutex->mutex );
|
||||
# elif defined( HB_COND_HARBOUR_SUPPORT )
|
||||
_hb_thread_cond_wait( &pSyncMutex->cond_l, &pSyncMutex->mutex, HB_THREAD_INFINITE_WAIT );
|
||||
# else
|
||||
HB_CRITICAL_UNLOCK( pSyncMutex->mutex );
|
||||
( void ) HB_COND_WAIT( pSyncMutex->cond_l );
|
||||
HB_CRITICAL_LOCK( pSyncMutex->mutex );
|
||||
# endif
|
||||
}
|
||||
pSyncMutex->lockers--;
|
||||
}
|
||||
pSyncMutex->lock_count = lock_count;
|
||||
pSyncMutex->owner = HB_THREAD_SELF();
|
||||
HB_CRITICAL_UNLOCK( pSyncMutex->mutex );
|
||||
}
|
||||
|
||||
hb_vmLock();
|
||||
}
|
||||
|
||||
return fResult;
|
||||
}
|
||||
#endif /* HB_MT_VM */
|
||||
|
||||
BOOL hb_threadMutexUnlock( PHB_ITEM pItem )
|
||||
{
|
||||
PHB_MUTEX pMutex = hb_mutexPtr( pItem );
|
||||
@@ -1838,7 +2005,7 @@ PHB_ITEM hb_threadMutexSubscribe( PHB_ITEM pItem, BOOL fClear )
|
||||
if( fClear && pMutex->events )
|
||||
hb_arraySize( pMutex->events, 0 );
|
||||
|
||||
/* release own locak from this mutex */
|
||||
/* release own lock from this mutex */
|
||||
if( HB_THREAD_EQUAL( pMutex->owner, HB_THREAD_SELF() ) )
|
||||
{
|
||||
lock_count = pMutex->lock_count;
|
||||
@@ -1949,7 +2116,7 @@ PHB_ITEM hb_threadMutexTimedSubscribe( PHB_ITEM pItem, ULONG ulMilliSec, BOOL fC
|
||||
|
||||
if( ulMilliSec && !( pMutex->events && hb_arrayLen( pMutex->events ) > 0 ) )
|
||||
{
|
||||
/* release own locak from this mutex */
|
||||
/* release own lock from this mutex */
|
||||
if( HB_THREAD_EQUAL( pMutex->owner, HB_THREAD_SELF() ) )
|
||||
{
|
||||
lock_count = pMutex->lock_count;
|
||||
|
||||
Reference in New Issue
Block a user