On Wed, 03 Jun 2009, Pritpal Bedi wrote:

Hi,

> After compiling the coffee.prg as in original post with 
> Harbour and Xbase++ I see the noticeable difference.
> Any programmer is able to fill the cup while coffee machine is still 
> preparing for the cofee. I mean Signal() | Wait() are not working as in
> Xbase++.
> ::coffeeIsReady:signal()
> :coffeeMachine:coffeeIsReady:wait()
> are not behaving as intended, probably.
> Can you please look into it.

It's possible and this is classic example which should be fixed by
real xbase++ users because xbase++ documentation you sent does not
inform about some important details of signal object implementation
and there are few different ways how they can be realized.

I left this message in method WAIT of SIGNAL object in rtl/tthreadx.prg

   /* TOCHECK: I do not know if strict Xbase++ compatibility needs
    *          hb_mutexSubscribe() or hb_mutexSubscribeNow()
    *          Please change it if necessary
    */

And probably if you change it then you will reach similar effect in
your code as in xbase++.
Anyhow I think it still will not replicate the exact xbase++ behavior.
Maybe it's documented and intentional one in OS2 where probably event
semaphores where used with explicit reset call but some code created
by xbase++ users and sent to this list cannot work properly with
such behavior of signal object. Such code needs buffered SIGNAL sent
before other thread executed WAIT but only one such signal should be
buffered. Now Harbour buffers all. So I guess that the signal object
in xbase++ has exactly the same behavior as binary (two states) semaphore.
To emulate such behavior you can add to SIGNAL method in TSIGNAL class:
   hb_mutexSubscribeNow( ::mutex, 0 )
just before:
   hb_mutexNotify( ::mutex )
but such version is not well synced and causes race condition so still two
threads can send signal and we do not have protection against buffering more
then one signal.
For correct emulation we have to make this two lines one atomic operation.
   hb_mutexSubscribeNow( ::mutex, 0 )
   hb_mutexNotify( ::mutex )
It can be quite easy and very efficient implemented in C code by extending
hb_mutexNotify() and adding new message only when queue is empty. Maybe
I'll add such functionality. Anyhow you can make it also in .prg code. It's
enough to declare SIGNAL method with SYNC attribute and you can be sure
that only one thread can execute above two functions what eliminates race
condition. But each object with SYNC methods needs additional mutex.
We already have one in ::mutex so we can use it explicitly. It's enough to
change SIGNAL method to:

   METHOD signal() CLASS TSIGNAL
      hb_mutexLock( ::mutex )
      hb_mutexSubscribeNow( ::mutex, 0 )
      hb_mutexNotify( ::mutex )
      hb_mutexUnLock( ::mutex )
      RETURN Self

Of course this are only my speculations about xbase++ which should be
verified by real xbase++ users. But it can be quite easy done.
Please check if it make the coffee machine code working like in xbase++.
If you can please also verify if signal object in xbase++ works exactly
like binary semaphore then it will be nice.

BTW AFAIK DISPOUTAT() in xbase++ is not Clipper compatible and works like
    HB_DISPOUTAT() in Harbour so probably it's good to add this line:
      #xtranslate dispoutat(<x,...>) => hb_dispoutat(<x>)
    at the beginning of your code to eliminate possible wrong color setting
    in output.

best regards,
Przemek
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to