On Fri, 21 Nov 2008, Pritpal Bedi wrote:

Hi Pritpal,

> > There is also yet another solution. You can create non HVM thread
> > which will be used to create all windows and process their message
> > queues. It will not make any other jobs so it will be always available
> > and other threads which may call locking windows API function will
> > not have to worry about deadlock because all locks used by window
> > owner thread will be known. This also resolve the problem of
> > automatic window refreshing.
> All other solutions are too much and all GTs must have to be modified
> to respect it.

Any final version will force code which have to be ready for MT mode
so it will have to be written in a little bit different way then for
ST. And I do not talk about Harbour API which may try to make more
friendly (though current code seems to be quite easy to use) but
Windows API which we cannot change and we have to accept suggested MS
solutions. Windows programmer have to carefully read MS documentation
and avoid any constructions which can create dead locks or race conditions.

> Non HVM thread creating windows and managing its message
> loop appears to be the right solution. It will also open some interesting
> possibilities. Can you guide me how this can be done? I will do all efforts
> to materialize it.

To clarify: it does not resolve everything. Just simply code has to be
written in different way. The main problem is accessing GT structures
from window message procedure. It has to be eliminated (for us it means
that we have to forbid resizing internal buffer in current form) or we
still will have to use GT locking and in such case updating existing
code which calls blocking functions to release and then restore GT lock
is a must so it will be good practice to locate all such places and
encapsulate them in UNLOCK/LOCK calls.
Otherwise we have to separate all variables used by GT thread and .prg
thread. It means that we will need our own screen buffer and it will not
be possible to call setmode() method from window procedure. So we will
have to forbid resizing (changing number of rows and calls) by user using
mouse or we will have to introduce some protocol which will allow resizing
when .prg thread will lock the GT to make some operations. In such case
GT window thread will only resize its internal buffer and set information
that GT buffer should be resizsed and it will be done when .prg thread
will access GT locking it. The REFRESH()/REDRAW() methods will copy data
from GT buffer to internal window buffer. This can be safely synchronized
by mutex because it's guarantied that non other locking functions will
be executed what may cause deadlock.
As you can see it's not such trivial operation though also not very
complicated. Please note that the separation and exchanging information
can be more restrictive. So far I said that we may need some protocol
to inform .prg thread about screen resizing. In fact we can exchange
all information using our own protocol and force full separation so
.prg thread will not call even single MS API function. Much more work
but as result we will have structures which can be served also by other
process or even on other computer. So it will be base for remote GT.
How to create it with minimal number of modifications:
1. just before creating first window we should create thread which will
   create it and then will process messages. We can even create an invisible
   window as message queue used to exchange data between .prg thread and the
   window thread but I do not think it will be necessary.
2. we should eliminate all calls to HB_GTSELF*()/HB_GTSUPER*() methods
   from window procedure and functions which are executed by window
   procedure. The same is for all other HVM functions like hb_item*()
   or hb_vm*().
   Later we can add some controlled support but now resizing GT buffer
   will be forbidden.
3. we should add internal buffer for window data used by window thread.
   This buffer will be updated from REFRESH()/REDRAW() methods and after
   updating InvalidateRect() will be executed to force redrawing by window
   thread. In GTWVG this buffer can be screen image. In GTWVT simple
   text buffer will be enough though we can also use screen image.
   If it will be necessary then this buffer can be protected by some
   local mutex. It will be safe if all operation executed when lock is
   set don't not need any other locks. In such case deadlock is impossible.
4. we will have to intorduce our own messages to force some actions executed
   by window thread. At least we will need:
      - create new window
      - close window
      - resize window
      - change font
   They should be blocking and return results like new window handler
   more or less directly (f.e. by setting some GT members).
   We can also add some other messages f.e. for palette modification.
   If possible other messages should be non blocking so we can benefit
   from parallel execution.

   Messages are automatically serialized by Windows so we will not need
   additional synchronization mechanism but we can also introduce it
   if it will help in some operations, f.e. see point 3.
5. we will need variables for cursor shape and position which will be
   updated in REFRESH() method and later used by window thread to
   control caret.
6. Keyboard input buffer is written in a way which allows to use it
   without any locks. There is race condition which can appear when
   buffer is full but it's not more danger then current behavior when
   new keys overwrite the last one what is Clipper compatible so
   READKEY() method can use it as is. We can only eliminate message
   processing which will not be necessary and what will increase the
   performance. Mouse methods we can leave as is.

This seems to be enough though probably some small problems will appear
during implementation but they should be easy to resolve. Eliminating
screen buffer from window procedure resizing greatly simplify the code.

> I do not use hb_gtInfoEx() as it also has sweare implications. About to be
> removed from the sources. You are right that this hack is dangerous.

hb_gtInfoEx() is not danger. The danger is the fact that this function
in current SVN is modified to call GTINFO() method without any GT clocks
so other threads can also access GT in the some time what can cause
internal data corruption.

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

Reply via email to