Hi Mindaugas, > thanks for a great sample code. It is great because it makes me to ask a > few questions, and to understand the details of process sync. > > There are things I do not like in this sample, and I'd like to make it > more perfect. The first thing I want to optimize is loop containing > sleep(0.01). This thread will require CPU 100 times per second, but > maybe my background task will be executed only every 5 minutes. I do not > want to waste a CPU time.
Exactly. It's not efficient. It was only an example. > So, the first question is, can I optimize my loop to avoid time checking > 100 times per second. I've tried to do this way: > static s_nDays := 0 > static function hb_backgroundThread() > local n, nTime, nMin > while !s_lStop > hb_mutexLock( s_mutex ) > nTime := seconds() + s_nDays > if nTime < s_nLastTime > nTime += 24*60*60 > s_nDays += 24*60*60 > endif > s_nLastTime = nTime > nMin := nTime + 24*60*60 > nTime *= 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_mutexUnlock( s_mutex ) > hb_idleSleep( nMin / 1000 ) > enddo > return nil 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(). > The second thing I want to implement is background thread exit, i.e., I > want to send some signal/mutex/semaphore/event from main thread to the > background thread and wait for exit using hb_threadJoin(). I'll need > some method to interrupt (possibly long) sleep. when background thread is created store value returned by hb_startThread() in static s_thread variable and then add this function: function hb_backgroundExit() if s_thread != NIL s_lStop := .t. hb_threadJoin( s_thread ) endif return nil > The other problem is, how to add new background tasks? I will also need > to interrupt sleep, because the execution time for new task can be > earlier than a time for existing tasks. > So, how can I implement an interruptable sleep and all required > synchronization objects? hb_idleSleep() is not good choice in such case. Use hb_mutexSubscribe() with timeout parameter, f.e.: hb_mutexSubscribe( s_mutex, nMin / 1000 ) and then you can wake up the thread waiting on mutex by simple hb_mutexNotify( s_mutex ) You should also change hb_backgroundExit() to wake up the thread: function hb_backgroundExit() if s_thread != NIL s_lStop := .t. hb_mutexNotify( s_mutex ) hb_threadJoin( s_thread ) endif return nil hb_mutexSubscribe() has yet another internal feature. When you call it and thread locked the mutex before then inside this function when thread is suspended mutex is automatically unlocked and then locked again before leaving hb_mutexSubscribe() It means that you can simplify then while loop above, f.e.: hb_mutexLock( s_mutex ) while !s_lStop [...] hb_mutexSubscribe( s_mutex, nMin / 1000 ) enddo hb_mutexUnlock( s_mutex ) Please also remember that hb_mutexSubscribe() can return immediately if some thread pushed some notification object before you call it. If you want to drop all previous notifications waiting in the mutex queue then you can use hb_mutexSubscribeNow() but please think if it does not cause problems for your code and some important events are not lost in such case. If you want then you can also use some values in hb_mutexNotify() and receive it as 3-rd parameter of hb_mutexSubscribe() to mark some actions. F.e. instead of using s_stop variable you can pass .T. as 2-nd hb_mutexNotify() parameter and then main loop you can look like: hb_mutexLock( s_mutex ) while .t. [...] if hb_mutexSubscribe( s_mutex, nMin / 1000, @xResult ) if valtype( xResult ) == "L" and xResult exit endif endif enddo hb_mutexUnlock( s_mutex ) In harbour/tests/mt/ you have simple demonstration programs which shows different synchronization mechanisms. They are not only tests. best regards, Przemek _______________________________________________ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour