On Fri, 19 Sep 2008, Pritpal Bedi wrote:

Hi Pritpal,

> Here is the message transcript on xHarbour NG:
[...]

xHarbour never had have working MT model. There is nothing
what even can be called MT model in this language. Just few
hacks to create and executes threads but serious problems
in core code was never resolved. In many cases not even touched.
Evan such basic functionality like safe readonly access to
complex variables was implemented few months ago by Walter
and only for MS-Win.
If you look carefully at xHarbour MT code you will find that
from thread startup there are bad race conditions.
Lexer, compiler and macro compiler are full of static variables
and are not MT safe. here at least there is protection: mutex
to block access to macro compiler so only one thread can access
it. It means that xHarbour MT programs which extensively use
macrocompiler are reduced to single CPU speed and they cannot
benefit from multiprocessor machines.
There is not protection for class definition which is kept
in single memory block and when new class is added this block
is resized. Because classes are added dynamically when calls
function is called 1-st time then such situation can happen
in any moment. It means that executing code which uses object
messages is not MT safe be. It can work for some programs but
it may also badly crashes - timed dependent race condtion.
Instead of redesigning memvars code for MT mode the memvars
table was moved to HVM stack as is from MT code. It forces
other things. xHarbour has to use thread local memvars and
there is no option for memvars sharing. But even this was
hacked because code for dynamic symbol table was also used
from ST mode without necessary modification. Instead hacks
where intorduced. In xHarbour MT mode all memvars are accessed
by _name_  not symbols. When thread access asign memvar then
to the mamavr name is added prefix: ":TH:" + <thread_id> + ":"
and such name is scann in dynamic symbol table. It's performance
killer and memory leak because symbol registered in dynamic
symbol tables cannot be removed. Beacuse thread uses cyclic IDs
repeated from 1 to 32000 (BTW also without protection against
non unique values but xHarbour has many such small bugs in MT code)
then in long working MT programs using memvars each used PRIVATE and
PUBLIC variable will be registered 32000 times in dynamic symbol
table. Of course it will not happen because xHarbour will crash.
Just simply the maximum number of dynamic symbols will be reached
earlier. In sumarry you cannot use memvars in real MT xHarbour
programs at all.
But it's not all. In the same table as memvars which was made thread
local are also kept detached local variables which can be accessed
by codeblocks. Such codeblocks can be storred in different places
which will be accessible after thread termination. F.e. in one of
the worst cases they maybe added to one of class definition.
When threads terminates its memvars pool is released by codeblocks
which detached local can be still accessible by other threads and
so when you try to evaluate them or _even_ delete you will have
GPF or other unexpected behavior because freed memory is accessed.
It means that they are corrupted forever and xHarbour will GPF
on HVM exit when will try to free all alocated items.
Result: you cannot use codeblocks with locals in xHarbour MT programs
or at least in very limited way _only_ in thread which created them
and you have to be sure that all their instances will be removed before
threads which created them terminates.
In practice all sets in xHarbour are global to application. It means
that there is not even way to use safely many things in xHarbour
by different threads without bad interactions. F.e. it's not possible
that one thread will operate on WA 1 with SET DELETED ON and second
one on WA 2 with SET DELETED OFF. It's not MT safe to use CODEPAGEs
in WA because for indexing RDDs switching active codepage which is
also global program setting not thread dependent, etc. You can imagine
all other bad interactions. It means that you cannot use many things
safely in xHarbour MT programs. F.e. even operating on different
RDDs is not fully MT safe and you have to be very carefull to not
change any of global settings.
The worka rea in xHarbour are not separated at all. It means that
each thread can access the same workare without _ANY_ protections.
To not GPF user have to create exclusive access to WA yourself.
It means that it have to be protect by user mutex, F.e.:

   static s_wa1mutex

   [...]

   s_wa1mutex := HB_MUTEXCREATE()   // INIT

   [...]

   HB_MUTEXLOCK( s_wa1mutex )       // LOCK WA

   [do sth with WA]

   HB_MUTEXUNLOCK( s_wa1mutex )     // UNLOCK WA

   [...]


It means that in xHarbour WA accessed is reduced to sth what
in xbase++ is called zero zone what is also supported by Harbout.
Just simply instead of using mutex LOCK/UNLOCK you are using
hb_dbDetach() and hb_dbRequest(). F.e. the same code in Harbour
may look like:


   [...]

   hb_dbDetach( "MYTABLE" )         // INIT

   [...]

   hb_waRequest( "MYTABLE" )       // LOCK WA

   [do sth with WA]

   hb_waDetach( "MYTABLE" )         // UNLOCK WA

   [...]

The difference is only in protection. In Harbour and xBase
user cannot corrupt WA by mistake due to missing warkarea lock
because locks are obligatory. In xHarbour they are not obligatory
and user any user mistake will corrupt internal RDD structures
causing unpredictable results, f.e. data lost or curruption.
Farther in xHarbour aliases are global to application so it's
not possible to create two independent threads which will use
aliases with the same name. You have to change your code to
eliminate such situatyions - of course if it's possible. As you
can emaigne sometimes it means that you have to rewrite in practice
whole code which uses aliases.
There are also many other things broken or not implemented in
xHarbour MT mode at all. If you are interesting then you can look
at xHarbour code. Some easy visible you will finde immediately
f.e. s_iBaseLine is static variable in hvm.c global for all
threads - it means that line numbering (PROCLINE()) does not
work correctly in MT programs. hb_vm_iTry is also static variable
used in TRY/CATCH statement. Any functionality related to this
variable does not work correctly in MT programs.
Such things can be easy fixed but if you will dig deeper then you
will find some other much more serious problems. Some of them
I described above. Bu not all f.e. in xHarbour destructors uses
hack in GC which uses s_bCollecting program global variable.
It's not MT safe so xHarbour MT programs cannot use destructors
or they may crash in unexpected places or block HVM/GC deadlocking
the whole application.
In summary if xHarbour developers will want to have really working
MT model then they will have to remove most of existing code and
implement it from scratch. But 1-st they will have to define how
it should work and what are their goals at beginning and cleanup
ST HVM resolving long waiting problems and bugs. Otherwise during
implementation they will find problems which cannot be easy resolved
without changing already written code and they will end with something
like they have now.
Enough, it's not my job to analyze xHarbour problems on on this
list.

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

Reply via email to