Hi,
Fine but I suggest to create separate function to extract number of
seconds from some starting day, f.e.:
HB_FUNC( HB_MILLISEC )
{
hb_retnin( hb_dateMilliSeconds() );
}
and use it instead of seconds().
Yes, it would be great.
In harbour/tests/mt/ you have simple demonstration programs which shows
different synchronization mechanisms. They are not only tests.
Thanks, for the answer. I've analysed /tests/mt, but I do not have
skills of MT programming. So, I expected we will need two more mutexes
for exit interrupt and for add new task interrupt. And I was unable to
imagine how can I wait for multiple events, something like:
hb_mutexSubscribe( {s_mutex, s_mutexExit, s_mutexAdd}, nMin/1000 )
But things become easy after you put a hand on it :)
So,I assume our current code is:
static function hb_backgroundThread()
local n, nTime, nMin
hb_mutexLock( s_mutex )
while !s_lStop
nTime := hb_MilliSeconds()
nMin := nTime + 24*60*60*1000
for n := 1 to s_nCounter
// {nHandle, bAction, nMilliSec, lActive, nNextTime}
if s_aTasks[ n, 4 ] .and. s_aTasks[ n, 5 ] <= nTime
eval( s_aTasks[ n, 2 ] )
s_aTasks[ n, 5 ] += s_aTasks[ n, 3 ]
endif
nMin := MIN( nMin, s_aTasks[ n, 5 ] )
next
hb_mutexSubscribe( s_mutex, nMin / 1000 )
enddo
hb_mutexUnlock( s_mutex )
return nil
function hb_backgroundExit()
if s_thread != NIL
s_lStop := .t.
hb_mutexNotify( s_mutex )
hb_threadJoin( s_thread )
endif
return nil
static function hb_backgroundInit()
if s_lStop
hb_threadOnce( @s_onceControl, {||
s_mutex := hb_mutexCreate()
hb_mutexLock( s_mutex )
s_lStop := .f.
s_thread := hb_threadStart( @hb_backgroundThread() )
hb_mutexUnlock( s_mutex )
return nil
} )
endif
return nil
function hb_backgroundAdd( bAction, nMilliSec, lActive )
local nHandler
if !HB_ISNUMERIC( nMilliSec )
nMilliSec := 0
endif
if ! HB_ISLOGICAL( lActive )
lActive := .t.
endif
hb_backgroundInit()
hb_mutexLock( s_mutex )
aadd( s_aTasks, { nHandler := ++s_nCounter, bAction, nMilliSec,
lActive, hb_MilliSeconds() + nMilliSec } )
hb_mutexUnlock( s_mutex )
return nHandler
and I still have two questions...
1) s_lStop access is synchronized using s_mutex. Is hb_backgroundExit()
code OK? Don't we need to change to:
function hb_backgroundExit()
if s_thread != NIL
hb_mutexLock( s_mutex )
s_lStop := .t.
hb_mutexNotify( s_mutex )
hb_mutexUnLock( s_mutex )
hb_threadJoin( s_thread )
endif
return nil
otherwise s_lStop can be assigned (by hb_backgroundExit) and accessed
(by hb_backgroundThread) simultaneous and give unpredictable results.
And here is a new question (well, 3 new questions...):
1a) is it OK to call hb_mutexNotify() if mutex is locked?
1b) will hb_mutexSubscribe() exit after hb_mutexUnLock() only? (because
it tries to lock mutex before exit)
1c) if 1b answer is "yes", then code:
hb_mutexLock( s_mutex )
s_lStop := .t.
hb_mutexNotify( s_mutex )
hb_threadJoin( s_thread )
hb_mutexUnLock( s_mutex )
will create deadlock. hb_threadJoin() will wait for child forever, but
child does not return from hb_mutexSubscribe() because trying to lock
mutex. Am I right?
The second question is:
2) I assume hb_backgroundAdd() could be called from any thread, and
hb_backgroundExit() is called from the main thread on application exit.
It is possible that s_thread != NIL will be false for the main thread,
but another thread is executing hb_backgroundAdd()/hb_backgroundInit()
that time. Let's say some code like:
s_mutex := hb_mutexCreate()
In this case the new thread will be started, but main thread will forget
to join it.
2a) do we need a mutex to protect s_thread access/assign?
2b) can we manage to use the same s_mutex, or we will need s_mutex2?
2c) where s_mutex2 should be initialized?
2d) I see STATIC s_mutex2 := hb_mutexCreate() in one of your last
commits. So, perhaps 2c answer is "Use STATIC initialization". Is it
possible to avoid static initialization? Or we will need one more
s_mutex3 to protect s_mutex2 initialization and this will be
never-ending story without STATICs.
Best regards,
Mindaugas
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour