diff --git a/harbour/ChangeLog b/harbour/ChangeLog index dc5213b8e8..fa90b9dc32 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -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. diff --git a/harbour/contrib/examples/uhttpd/uhttpd.prg b/harbour/contrib/examples/uhttpd/uhttpd.prg index e176809197..26ffff94cf 100644 --- a/harbour/contrib/examples/uhttpd/uhttpd.prg +++ b/harbour/contrib/examples/uhttpd/uhttpd.prg @@ -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 diff --git a/harbour/contrib/examples/uhttpd/uhttpdc.c b/harbour/contrib/examples/uhttpd/uhttpdc.c index 18e6259282..e17aa20048 100644 --- a/harbour/contrib/examples/uhttpd/uhttpdc.c +++ b/harbour/contrib/examples/uhttpd/uhttpdc.c @@ -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; diff --git a/harbour/include/hbthread.h b/harbour/include/hbthread.h index df56fd60c2..17650d3981 100644 --- a/harbour/include/hbthread.h +++ b/harbour/include/hbthread.h @@ -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 diff --git a/harbour/source/rtl/hbinet.c b/harbour/source/rtl/hbinet.c index 8954d6b035..3371b382ec 100644 --- a/harbour/source/rtl/hbinet.c +++ b/harbour/source/rtl/hbinet.c @@ -1453,7 +1453,7 @@ HB_FUNC( HB_INETDATAREADY ) return; } - if( ISNUM( 1 ) ) + if( ISNUM( 2 ) ) { iVal = hb_parni( 2 ); tv.tv_sec = iVal / 1000; diff --git a/harbour/source/vm/thread.c b/harbour/source/vm/thread.c index a4dec71bcf..c4dd417982 100644 --- a/harbour/source/vm/thread.c +++ b/harbour/source/vm/thread.c @@ -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;