2009-03-09 00:19 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbthread.h
* harbour/source/vm/thread.c
* emulate POSIX thread conditional variables in Windows builds.
It should fix some possible bad behavior in MS-Windows Harbour
MT programs.
* harbour/source/rtl/hbinet.c
! fixed typo in HB_INETDATAREADY() - the second parameter (timeout)
was ignored.
* harbour/contrib/examples/uhttpd/uhttpdc.c
* fixed typo in conditional iMsec usage.
* harbour/contrib/examples/uhttpd/uhttpd.prg
* set default timeout for socket operations to 3 sec.
* use timeout parameter in HB_INETDATAREADY() and
increased default timeout for accept to 250 millisecs.
Please correct this modification if you prefer different values.
This commit is contained in:
@@ -8,6 +8,26 @@
|
||||
2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org)
|
||||
*/
|
||||
|
||||
2009-03-09 00:19 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/include/hbthread.h
|
||||
* harbour/source/vm/thread.c
|
||||
* emulate POSIX thread conditional variables in Windows builds.
|
||||
It should fix some possible bad behavior in MS-Windows Harbour
|
||||
MT programs.
|
||||
|
||||
* harbour/source/rtl/hbinet.c
|
||||
! fixed typo in HB_INETDATAREADY() - the second parameter (timeout)
|
||||
was ignored.
|
||||
|
||||
* harbour/contrib/examples/uhttpd/uhttpdc.c
|
||||
* fixed typo in conditional iMsec usage.
|
||||
|
||||
* harbour/contrib/examples/uhttpd/uhttpd.prg
|
||||
* set default timeout for socket operations to 3 sec.
|
||||
* use timeout parameter in HB_INETDATAREADY() and
|
||||
increased default timeout for accept to 250 millisecs.
|
||||
Please correct this modification if you prefer different values.
|
||||
|
||||
2009-03-08 19:29 UTC+0100 Viktor Szakats (harbour.01 syenar hu)
|
||||
* contrib/examples/uhttpd/uhttpdgd.hbm
|
||||
+ Added Darwin/MacPorts support.
|
||||
|
||||
@@ -449,8 +449,10 @@ FUNCTION MAIN( ... )
|
||||
? "Bind Error"
|
||||
ELSE
|
||||
|
||||
s_nLocalPort := hb_InetPort( hListen )
|
||||
s_cLocalAddress := hb_InetAddress( hListen )
|
||||
s_nLocalPort := hb_InetPort( hListen )
|
||||
s_cLocalAddress := hb_InetAddress( hListen )
|
||||
|
||||
hb_InetTimeOut( hListen, 3000 )
|
||||
|
||||
#else
|
||||
hListen := socket_create()
|
||||
@@ -512,8 +514,7 @@ FUNCTION MAIN( ... )
|
||||
|
||||
// Wait a connection
|
||||
#ifdef USE_HB_INET
|
||||
hb_InetTimeOut( hListen, 50 )
|
||||
IF HB_InetDataReady( hListen ) > 0
|
||||
IF HB_InetDataReady( hListen, 250 ) > 0
|
||||
#else
|
||||
IF socket_select( { hListen },,, 50 ) > 0
|
||||
#endif
|
||||
|
||||
@@ -76,7 +76,7 @@ BOOL win_SysRefresh( int iMsec )
|
||||
/* Begin the operation and continue until it is complete
|
||||
or until the user clicks the mouse or presses a key. */
|
||||
|
||||
while( MsgWaitForMultipleObjects( 1, &hDummyEvent, FALSE, ( iMsec == 0, INFINITE, iMsec ), QS_ALLINPUT | QS_ALLPOSTMESSAGE) == WAIT_OBJECT_0 + 1 )
|
||||
while( MsgWaitForMultipleObjects( 1, &hDummyEvent, FALSE, ( iMsec == 0 ? INFINITE : ( ULONG ) iMsec ), QS_ALLINPUT | QS_ALLPOSTMESSAGE) == WAIT_OBJECT_0 + 1 )
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
|
||||
@@ -125,13 +125,11 @@ HB_EXTERN_BEGIN
|
||||
|
||||
#elif defined( HB_OS_WIN ) && ! defined( HB_OS_WIN_CE )
|
||||
|
||||
# define HB_MAX_THREAD 32768
|
||||
|
||||
typedef HB_LONG HB_THREAD_NO;
|
||||
typedef unsigned HB_THREAD_ID;
|
||||
typedef HANDLE HB_THREAD_HANDLE;
|
||||
typedef CRITICAL_SECTION HB_RAWCRITICAL_T;
|
||||
typedef HANDLE HB_RAWCOND_T;
|
||||
typedef HANDLE HB_OSCOND_T;
|
||||
|
||||
# define HB_THREAD_STARTFUNC( func ) unsigned __stdcall func( void * Cargo )
|
||||
# define HB_THREAD_END _endthreadex( 0 ); return 0;
|
||||
@@ -139,22 +137,16 @@ HB_EXTERN_BEGIN
|
||||
|
||||
# define HB_THREAD_SELF() GetCurrentThreadId()
|
||||
# define HB_CRITICAL_INITVAL { 0, 0, 0, 0, 0, 0 }
|
||||
# define HB_COND_INITVAL ( ( HANDLE ) NULL )
|
||||
|
||||
# define HB_CRITICAL_INIT(v) InitializeCriticalSection( &(v) )
|
||||
# define HB_CRITICAL_DESTROY(v) DeleteCriticalSection( &(v) )
|
||||
# define HB_CRITICAL_LOCK(v) EnterCriticalSection( &(v) )
|
||||
# define HB_CRITICAL_UNLOCK(v) LeaveCriticalSection( &(v) )
|
||||
# define HB_COND_INIT(v) do { (v) = CreateSemaphore( NULL, 0, HB_MAX_THREAD, NULL ); } while(0)
|
||||
# define HB_COND_DESTROY(v) CloseHandle( v )
|
||||
# define HB_COND_SIGNAL(v) ReleaseSemaphore( (v), 1, NULL )
|
||||
# define HB_COND_SIGNALN(v,n) ReleaseSemaphore( (v), (n), NULL )
|
||||
# define HB_COND_WAIT(v) ( WaitForSingleObject( (v), INFINITE ) != WAIT_FAILED )
|
||||
# define HB_COND_TIMEDWAIT(v,n) ( WaitForSingleObject( (v), (n) ) != WAIT_FAILED )
|
||||
|
||||
# undef HB_COND_OS_SUPPORT
|
||||
# undef HB_COND_NEED_INIT
|
||||
# define HB_COND_HARBOUR_SUPPORT
|
||||
# define HB_CRITICAL_NEED_INIT
|
||||
# define HB_COND_NEED_INIT
|
||||
|
||||
# define HB_THREAD_INFINITE_WAIT INFINITE
|
||||
|
||||
@@ -169,30 +161,15 @@ HB_EXTERN_BEGIN
|
||||
typedef TID HB_THREAD_ID;
|
||||
typedef TID HB_THREAD_HANDLE;
|
||||
typedef HMTX HB_RAWCRITICAL_T;
|
||||
typedef HEV HB_OSCOND_T;
|
||||
|
||||
extern ULONG _hb_gettid( void );
|
||||
|
||||
typedef struct _HB_WAIT_LIST
|
||||
{
|
||||
struct _HB_WAIT_LIST * prev;
|
||||
struct _HB_WAIT_LIST * next;
|
||||
HEV cond;
|
||||
BOOL signaled;
|
||||
} HB_WAIT_LIST, * PHB_WAIT_LIST;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PHB_WAIT_LIST waiters;
|
||||
} HB_COND_T, HB_RAWCOND_T;
|
||||
|
||||
# define HB_COND_NEW( name ) HB_COND_T name = { NULL }
|
||||
|
||||
# define HB_THREAD_STARTFUNC( func ) void func( void * Cargo )
|
||||
# define HB_THREAD_END _endthread(); return;
|
||||
# define HB_THREAD_RAWEND return;
|
||||
|
||||
# define HB_CRITICAL_INITVAL ( ( HMTX ) 0 )
|
||||
# define HB_COND_INITVAL ( ( HEV ) 0 )
|
||||
# if defined( __GNUC__ )
|
||||
# define HB_THREAD_SELF() ( ( TID ) _gettid() )
|
||||
# else
|
||||
@@ -203,10 +180,6 @@ HB_EXTERN_BEGIN
|
||||
# define HB_CRITICAL_DESTROY(v) DosCloseMutexSem( v )
|
||||
# define HB_CRITICAL_LOCK(v) DosRequestMutexSem( (v), SEM_INDEFINITE_WAIT )
|
||||
# define HB_CRITICAL_UNLOCK(v) DosReleaseMutexSem( v )
|
||||
# define HB_COND_SIGNAL(v) _hb_thread_cond_signal( &(v) )
|
||||
# define HB_COND_SIGNALN(v,n) _hb_thread_cond_broadcast( &(v) )
|
||||
# define HB_COND_WAIT(v) _hb_thread_cond_wait( (v), SEM_INDEFINITE_WAIT )
|
||||
# define HB_COND_TIMEDWAIT(v,n) _hb_thread_cond_wait( (v), (n) )
|
||||
|
||||
# undef HB_COND_OS_SUPPORT
|
||||
# undef HB_COND_NEED_INIT
|
||||
@@ -242,6 +215,29 @@ HB_EXTERN_BEGIN
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( HB_COND_HARBOUR_SUPPORT )
|
||||
|
||||
typedef struct _HB_WAIT_LIST
|
||||
{
|
||||
struct _HB_WAIT_LIST * prev;
|
||||
struct _HB_WAIT_LIST * next;
|
||||
HB_OSCOND_T cond;
|
||||
BOOL signaled;
|
||||
} HB_WAIT_LIST, * PHB_WAIT_LIST;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PHB_WAIT_LIST waiters;
|
||||
} HB_COND_T, HB_RAWCOND_T;
|
||||
|
||||
# define HB_COND_NEW( name ) HB_COND_T name = { NULL }
|
||||
|
||||
# define HB_COND_SIGNAL(v) _hb_thread_cond_signal( &(v) )
|
||||
# define HB_COND_SIGNALN(v,n) _hb_thread_cond_broadcast( &(v) )
|
||||
# define HB_COND_WAIT(v) _hb_thread_cond_wait( (v), HB_THREAD_INFINITE_WAIT )
|
||||
# define HB_COND_TIMEDWAIT(v,n) _hb_thread_cond_wait( (v), (n) )
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HB_CRITICAL_NEED_INIT
|
||||
typedef struct
|
||||
|
||||
@@ -1453,7 +1453,7 @@ HB_FUNC( HB_INETDATAREADY )
|
||||
return;
|
||||
}
|
||||
|
||||
if( ISNUM( 1 ) )
|
||||
if( ISNUM( 2 ) )
|
||||
{
|
||||
iVal = hb_parni( 2 );
|
||||
tv.tv_sec = iVal / 1000;
|
||||
|
||||
@@ -184,7 +184,7 @@ void hb_threadExit( void )
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( HB_OS_OS2 ) && defined( HB_MT_VM )
|
||||
#if defined( HB_MT_VM ) && defined( HB_COND_HARBOUR_SUPPORT )
|
||||
static PHB_WAIT_LIST _hb_thread_wait_list( void )
|
||||
{
|
||||
PHB_THREADSTATE pThread = ( PHB_THREADSTATE ) hb_vmThreadState();
|
||||
@@ -197,9 +197,15 @@ static PHB_WAIT_LIST _hb_thread_wait_list( void )
|
||||
|
||||
static void _hb_thread_wait_add( HB_COND_T * cond, PHB_WAIT_LIST pWaiting )
|
||||
{
|
||||
#if defined( HB_OS_OS2 )
|
||||
ULONG ulPostCount = 0;
|
||||
|
||||
DosResetEventSem( pWaiting->cond, &ulPostCount );
|
||||
#elif defined( HB_OS_WIN )
|
||||
/* It's not necessary becayse we have workaround for possible race
|
||||
* condition inside _hb_thread_cond_wait() function
|
||||
*/
|
||||
/* WaitForSingleObject( pWaiting->cond, 0 ); */
|
||||
#endif
|
||||
pWaiting->signaled = FALSE;
|
||||
|
||||
if( cond->waiters == NULL )
|
||||
@@ -235,7 +241,11 @@ static BOOL _hb_thread_cond_signal( HB_COND_T * cond )
|
||||
{
|
||||
if( !pWaiting->signaled )
|
||||
{
|
||||
#if defined( HB_OS_OS2 )
|
||||
DosPostEventSem( pWaiting->cond );
|
||||
#elif defined( HB_OS_WIN )
|
||||
ReleaseSemaphore( pWaiting->cond, 1, NULL );
|
||||
#endif
|
||||
pWaiting->signaled = TRUE;
|
||||
/* signal only single thread */
|
||||
break;
|
||||
@@ -257,7 +267,11 @@ static BOOL _hb_thread_cond_broadcast( HB_COND_T * cond )
|
||||
{
|
||||
if( !pWaiting->signaled )
|
||||
{
|
||||
#if defined( HB_OS_OS2 )
|
||||
DosPostEventSem( pWaiting->cond );
|
||||
#elif defined( HB_OS_WIN )
|
||||
ReleaseSemaphore( pWaiting->cond, 1, NULL );
|
||||
#endif
|
||||
pWaiting->signaled = TRUE;
|
||||
}
|
||||
pWaiting = pWaiting->next;
|
||||
@@ -277,9 +291,18 @@ static BOOL _hb_thread_cond_wait( HB_COND_T * cond, HB_RAWCRITICAL_T * critical,
|
||||
{
|
||||
_hb_thread_wait_add( cond, pWaiting );
|
||||
|
||||
#if defined( HB_OS_OS2 )
|
||||
DosReleaseMutexSem( *critical );
|
||||
fResult = DosWaitEventSem( pWaiting->cond, ulMillisec ) == NO_ERROR;
|
||||
DosRequestMutexSem( *critical, SEM_INDEFINITE_WAIT );
|
||||
#elif defined( HB_OS_WIN )
|
||||
LeaveCriticalSection( critical );
|
||||
fResult = WaitForSingleObject( pWaiting->cond, ulMillisec ) == WAIT_OBJECT_0;
|
||||
EnterCriticalSection( critical );
|
||||
/* workaround for race condition */
|
||||
if( !fResult && pWaiting->signaled )
|
||||
fResult = WaitForSingleObject( pWaiting->cond, 0 ) == WAIT_OBJECT_0;
|
||||
#endif
|
||||
|
||||
_hb_thread_wait_del( cond, pWaiting );
|
||||
}
|
||||
@@ -519,7 +542,7 @@ BOOL hb_threadCondWait( HB_COND_T * cond, HB_CRITICAL_T * mutex )
|
||||
fResult = HB_COND_WAIT( cond->cond );
|
||||
HB_CRITICAL_LOCK( mutex->critical );
|
||||
/* There is race condition here and user code should always check if
|
||||
* if the wait condition is valid after leaving hb_threadCondWait()
|
||||
* the wait condition is valid after leaving hb_threadCondWait()
|
||||
* even if it returns TRUE
|
||||
*/
|
||||
if( !fResult )
|
||||
@@ -576,7 +599,7 @@ BOOL hb_threadCondTimedWait( HB_COND_T * cond, HB_CRITICAL_T * mutex, ULONG ulMi
|
||||
fResult = HB_COND_TIMEDWAIT( cond->cond, ulMilliSec );
|
||||
HB_CRITICAL_LOCK( mutex->critical );
|
||||
/* There is race condition here and user code should always check if
|
||||
* if the wait condition is valid after leaving hb_threadCondTimedWait()
|
||||
* the wait condition is valid after leaving hb_threadCondTimedWait()
|
||||
* even if it returns TRUE
|
||||
*/
|
||||
if( !fResult )
|
||||
@@ -711,11 +734,16 @@ static HB_GARBAGE_FUNC( hb_threadDestructor )
|
||||
hb_gtRelease( pThread->hGT );
|
||||
pThread->hGT = NULL;
|
||||
}
|
||||
#if defined( HB_OS_OS2 )
|
||||
#if defined( HB_COND_HARBOUR_SUPPORT )
|
||||
if( pThread->pWaitList.cond )
|
||||
{
|
||||
# if defined( HB_OS_OS2 )
|
||||
DosCloseEventSem( pThread->pWaitList.cond );
|
||||
pThread->pWaitList.cond = ( HEV ) 0;
|
||||
# elif defined( HB_OS_WIM )
|
||||
CloseHandle( pThread->pWaitList.cond );
|
||||
pThread->pWaitList.cond = ( HANDLE ) 0;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -815,8 +843,12 @@ PHB_THREADSTATE hb_threadStateNew( void )
|
||||
pThread->pThItm = pThItm;
|
||||
pThread->hGT = hb_gtAlloc( NULL );
|
||||
|
||||
#if defined( HB_OS_OS2 )
|
||||
DosCreateEventSem( NULL, &pThread->pWaitList.cond, 0L, FALSE );
|
||||
#if defined( HB_COND_HARBOUR_SUPPORT )
|
||||
# if defined( HB_OS_OS2 )
|
||||
DosCreateEventSem( NULL, &pThread->pWaitList.cond, 0L, FALSE );
|
||||
# elif defined( HB_OS_WIM )
|
||||
pThread->pWaitList.cond = CreateSemaphore( NULL, 0, 1, NULL );
|
||||
# endif
|
||||
#endif
|
||||
|
||||
return pThread;
|
||||
|
||||
Reference in New Issue
Block a user