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