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:
Przemyslaw Czerpak
2009-03-08 23:15:18 +00:00
parent bdc2d3c33c
commit 016078ef85
6 changed files with 93 additions and 44 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -1453,7 +1453,7 @@ HB_FUNC( HB_INETDATAREADY )
return;
}
if( ISNUM( 1 ) )
if( ISNUM( 2 ) )
{
iVal = hb_parni( 2 );
tv.tv_sec = iVal / 1000;

View File

@@ -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;