Author | Topic: Xbase++ 1.9 feature request | |
---|---|---|
Hannes Ziegler | Xbase++ 1.9 feature request on Sat, 16 Apr 2005 01:45:32 +0200 One thing I'd like to be included ASAP in Xbase++ is this -> enable Xbase++ programmers to register windows created with WinAPI functions on the Event Manager Thread (EVM) This is the most limiting factor for the future of Xbase++: Window handles cannot be registered in the internal Xbase++ threads. I can create an own window via DllCall() and the WinAPI functions CreateWindow()/CreateWIndowEx() but they are not recognized by AppEvent(). Instead, I have to use my own message handling via GetMessage()/TranslateMessage()/DispatchMessage(). I want my CreateWindow() window to be recognized by AppEvent() Hannes | |
Phil Ide | Re: Xbase++ 1.9 feature request on Mon, 18 Apr 2005 09:39:43 +0100 Hannes, > -> enable Xbase++ programmers to register windows created with WinAPI > functions on the Event Manager Thread (EVM) > > This is the most limiting factor for the future of Xbase++: > > Window handles cannot be registered in the internal Xbase++ threads. I > can create an own window via DllCall() and the WinAPI functions > CreateWindow()/CreateWIndowEx() but they are not recognized by > AppEvent(). Instead, I have to use my own message handling via > GetMessage()/TranslateMessage()/DispatchMessage(). > > I want my CreateWindow() window to be recognized by AppEvent() Then you'll run into the problem that Xbase++ filters events, and you want access to events AppEvent() doesn't expose. You would be better off with the GetMessage()/TranslateMessage()/DispatchMessage() sequence and writing a wrapper which pols the Xbase++ AppEvent for Xbp events - but hey, isn't this going down the same road as Cockpit? Regards, Phil Ide *************************************** * Xbase++ FAQ, Libraries and Sources: * * goto: http://www.idep.org.uk/xbase * *************************************** Scrut the inscrutable and eff the ineffable! | |
Hannes Ziegler | Re: Xbase++ 1.9 feature request on Tue, 19 Apr 2005 02:53:02 +0200 Phil, > Then you'll run into the problem that Xbase++ filters events, and you want > access to events AppEvent() doesn't expose. You would be better off with > the GetMessage()/TranslateMessage()/DispatchMessage() sequence and writing > a wrapper which pols the Xbase++ AppEvent for Xbp events - but hey, isn't > this going down the same road as Cockpit? Well, methinks that Cockpit suffers from the very same problem and this problem is the major cause for a reluctant acceptance of Cockpit. FWIW, Xbase++ must send messages to windows that don't belong to an Xbase++ app. When we assume that message handling is done in the internal EVM thread, there must be a distinction between window handles that belong to the Xbase++ app and the ones that don't belong to it. If I create window handles with CreateWindow(), they seem to not belong to the Xbase++ app. Maybe I should say better: CreateWindow() windows are no XbaseParts. IMO, the EVM thread handles window messages internally for windows that are no XbaseParts, which means, these events don't show up on the Xbase++ language level with AppEvent(). To specify my request: the Xbase++ EVM thread should send all events to my window handle when this window handle is PART of my Xbase++ app, but not an XbasePart. Many windows don't fulfill this requirement (all that don't belong to the Xbase++ app). That's why I'd like to explicitly register a window handle within my Xbase++ app on the EVM thread. BTW, the fact that Cockpit allows for mixing XbasePart windows and native windows is no excuse for Alaska's design flaw. It simply tells that Michael is a pretty smart programmer. Regards, -- Hannes | |
James Loughner | Re: Xbase++ 1.9 feature request on Tue, 19 Apr 2005 00:54:28 -0400 Well Hannes I for one want this abstraction layer. I don't want Xbase++ married to Windows. This abstraction is needed to make the base language separate from and independent from the OS. I want to be able to compile essentially the same code for Linux and Windows or even Unix and OSX. If the syntax is tied too closely to Windows you fall into the M$ trap. We are all caught in the trap at the moment. I would love to get out of it. It is the one feature of xHarbor that is interesting to me. The only thing stopping me is the tons of OOP code I have written to XBP's If someone really needs some Windows specific function then there is always Cockpit or Active-X. The answer would be a Mono compliant language that would also run on .NET. Jim Hannes Ziegler wrote: > Phil, > > >>Then you'll run into the problem that Xbase++ filters events, and you want >>access to events AppEvent() doesn't expose. You would be better off with >>the GetMessage()/TranslateMessage()/DispatchMessage() sequence and writing >>a wrapper which pols the Xbase++ AppEvent for Xbp events - but hey, isn't >>this going down the same road as Cockpit? > > > Well, methinks that Cockpit suffers from the very same problem and this > problem is the major cause for a reluctant acceptance of Cockpit. > > FWIW, Xbase++ must send messages to windows that don't belong to an > Xbase++ app. When we assume that message handling is done in the > internal EVM thread, there must be a distinction between window handles > that belong to the Xbase++ app and the ones that don't belong to it. > > If I create window handles with CreateWindow(), they seem to not belong > to the Xbase++ app. Maybe I should say better: CreateWindow() windows > are no XbaseParts. > > IMO, the EVM thread handles window messages internally for windows that > are no XbaseParts, which means, these events don't show up on the > Xbase++ language level with AppEvent(). > > To specify my request: the Xbase++ EVM thread should send all events to > my window handle when this window handle is PART of my Xbase++ app, but > not an XbasePart. Many windows don't fulfill this requirement (all that > don't belong to the Xbase++ app). That's why I'd like to explicitly > register a window handle within my Xbase++ app on the EVM thread. > > BTW, the fact that Cockpit allows for mixing XbasePart windows and > native windows is no excuse for Alaska's design flaw. It simply tells > that Michael is a pretty smart programmer. > > Regards, > -- > Hannes | |
Hannes Ziegler | Re: Xbase++ 1.9 feature request on Wed, 20 Apr 2005 03:04:44 +0200 James, > I for one want this abstraction layer. I don't want Xbase++ married to > Windows. This abstraction is needed to make the base language separate > from and independent from the OS. I want to be able to compile > essentially the same code for Linux and Windows or even Unix and OSX. If > the syntax is tied too closely to Windows you fall into the M$ trap. We > are all caught in the trap at the moment. I would love to get out of it. > It is the one feature of xHarbor that is interesting to me. The only > thing stopping me is the tons of OOP code I have written to XBP's I agree with you to about 90%. Xbase++ provides a high abstraction layer when it comes to event handling, and this is a real strength. However, the 10% I disagree with you is where I loose my freedom and flexibility as a programmer. I'm sure the Alaska guys could provide a way for us to register our own window handles on the EVM thread. Even if that means that we have to create XBP like data structures around our window handles. Regards, -- Hannes | |
Phil Ide | Re: Xbase++ 1.9 feature request on Tue, 19 Apr 2005 09:59:58 +0100 Hannes, > To specify my request: the Xbase++ EVM thread should send all events to > my window handle when this window handle is PART of my Xbase++ app, but > not an XbasePart. Many windows don't fulfill this requirement (all that > don't belong to the Xbase++ app). That's why I'd like to explicitly > register a window handle within my Xbase++ app on the EVM thread. > > BTW, the fact that Cockpit allows for mixing XbasePart windows and > native windows is no excuse for Alaska's design flaw. It simply tells > that Michael is a pretty smart programmer. Without trying to be negative, whilst Michael is a smart programmer, Cockpit is a result of a basic desire to bridge Xbase++ and C/C++ routines, and is simply (he says, understating it) the natural evolution of this desire. Where Cockpit stands clear of the crowd, in software terms, is that Michael had the foresight and vision to create an architecture and API that satisfies the very broad range of requirements to make that bridge both all-encompassing (in terms of features) and consistent. Consistent not only within the Cockpit package, but in terms the Xbase++ language as well. Xbase++ presents a vastly different paradigm for event handling from Windows, both architecturally and in the way you program the events, yet Michael has managed to bridge both paradigm's without making it look too alien to us mere mortals. To answer your original request, I think that a perfect solution would be the ability to state to the runtime on three different levels, how to handle events - the default XPP way or otherwise: 1. Global statement: SET EVENT_NOTIFICATION XPP default SET EVENT_NOTIFICATION WINDOWS pass all events to all windows 2. Per Window: oDlg:setEVMode(EVENT_MODE_WINDOWS) receive all events 3. Per Event by Window: oDlg:RecvEvent(FD_READ) receive FD_READ event Regards, Phil Ide *************************************** * Xbase++ FAQ, Libraries and Sources: * * goto: http://www.idep.org.uk/xbase * *************************************** Drive C: Error, (A)bort (R)etry (I)gnore (K)ick (S)cream | |
Hannes Ziegler | Re: Xbase++ 1.9 feature request on Wed, 20 Apr 2005 03:24:02 +0200 Phil, I tend to disagree with you to a higher percentage than with James First, I won't discuss Michael's Cockpit approch unless he is present. Michael has done a tremendous work. His life could have been easier, if he were able to register CreateWindow() handles within the EVM thread. Better to say: if it would be possible in Xbase++ to tell AppEvent() to recognize CreateWindow() handles . > Xbase++ presents a vastly different paradigm for event handling from > Windows, both architecturally and in the way you program the events, yet > Michael has managed to bridge both paradigm's without making it look too > alien to us mere mortals. Xbase++ relies on the events fired by the OS. This is hidden from the Xbase++ programmer for some very good reasons dating back to 1996. However, there are a number of reasons grown until 2005 why Xbase++ should give an Xbase++ programmer full control over the events fired by the OS. > To answer your original request, I think that a perfect solution would be > the ability to state to the runtime on three different levels, how to > handle events - the default XPP way or otherwise: > > 1. Global statement: > SET EVENT_NOTIFICATION XPP default > SET EVENT_NOTIFICATION WINDOWS pass all events to all windows > > 2. Per Window: > oDlg:setEVMode(EVENT_MODE_WINDOWS) receive all events > > 3. Per Event by Window: > oDlg:RecvEvent(FD_READ) receive FD_READ event Well, I think the better approach is that Alaska documents how to embed a window handle within an XbasePart data structure and how to register it on the EVM thread. This way, user defined window handles are recognized by AppEvent(). Regards, -- Hannes | |
Phil Ide | Re: Xbase++ 1.9 feature request on Wed, 20 Apr 2005 09:49:37 +0100 Hannes, > Well, I think the better approach is that Alaska documents how to embed > a window handle within an XbasePart data structure and how to register > it on the EVM thread. This way, user defined window handles are > recognized by AppEvent(). Yes, but then the EVM thread will still consume some events which today we do not see but wish to. Regards, Phil Ide *************************************** * Xbase++ FAQ, Libraries and Sources: * * goto: http://www.idep.org.uk/xbase * *************************************** Espresso: ultra-efficient caffeine delivery system | |
Hannes Ziegler | Re: Xbase++ 1.9 feature request on Fri, 22 Apr 2005 01:51:52 +0200 Phil, > > Well, I think the better approach is that Alaska documents how to embed > > a window handle within an XbasePart data structure and how to register > > it on the EVM thread. This way, user defined window handles are > > recognized by AppEvent(). > > Yes, but then the EVM thread will still consume some events which today we > do not see but wish to. AFAIK, this problem has been anticipated already in Xbase++, but a solution is not implemented. Before we continue in speculations about the best implementation, let me state again: The only thing I want is, register my CreateWindow() windows on the EVM thread so that they are recognized by AppEvent(). IMO, thats not our job to do it. Its part of Alaska's homework. I'm deeply convinced that a solution of the window handle/EVM thread problem serves the Xbase++ product better than an AutomationObject(). Regards, -- Hannes | |
Phil Ide | Re: Xbase++ 1.9 feature request on Fri, 22 Apr 2005 10:03:22 +0100 Hannes, >> Yes, but then the EVM thread will still consume some events which today we >> do not see but wish to. > > AFAIK, this problem has been anticipated already in Xbase++, but a > solution is not implemented. Yes, and wen it is implemented, it will be a big relief > The only thing I want is, register my CreateWindow() windows on the EVM > thread so that they are recognized by AppEvent(). ACK, I understand, and I'm not disagreeing with you - that would make a formidable difference to Xbase++. > I'm deeply convinced that a solution of the window handle/EVM thread > problem serves the Xbase++ product better than an AutomationObject(). Well, that's debateable depending upon the requirements of individual users and projects, but it would certainly be one of the most significant changes you could make to Xbase++. Regards, Phil Ide *************************************** * Xbase++ FAQ, Libraries and Sources: * * goto: http://www.idep.org.uk/xbase * *************************************** Sometimes, I wish I could PKZIP my wife! | |
Gnter Beyes | Re: Xbase++ 1.9 feature request on Wed, 20 Apr 2005 11:20:04 +0200 On Sat, 16 Apr 2005 01:45:32 +0200, Hannes Ziegler <Hannes_Ziegler@Compuserve.com> wrote: >One thing I'd like to be included ASAP in Xbase++ is this > > enable Xbase++ programmers to register windows created with WinAPI >functions on the Event Manager Thread (EVM) > >This is the most limiting factor for the future of Xbase++: > >Window handles cannot be registered in the internal Xbase++ threads. I >can create an own window via DllCall() and the WinAPI functions >CreateWindow()/CreateWIndowEx() but they are not recognized by >AppEvent(). Instead, I have to use my own message handling via >GetMessage()/TranslateMessage()/DispatchMessage(). Hannes, unfortunately, for the EVM thread to see any messages related to a specific window, that window <b>must have been created</b> by the EVM thread itself. To be fair, that's just the way Windows works, no Alaska design flaw. Messages to a window are delivered only to the thread that created it. The links below do emphasize this, and also show what this implies for hosting ActiveX controls. (That's what you're essentially driving at, I presume.) + "Concurrency and Windows", by Larry Osterman http://blogs.msdn.com/larryosterman/archive/2005/03/22/400583.aspx + Understanding COM Apartments, Part I & II, by Jeff Prosise http://www.codeguru.com/Cpp/COM-Tech/activex/apts/article.php/c5529/ http://www.codeguru.com/Cpp/COM-Tech/activex/apts/article.php/c5533/ + PRB: "The Remote Procedure Call Failed" During OLE Automation http://support.microsoft.com/kb/181894/EN-US/ Quote from the latter: "Every thread that uses COM or OLE must call CoInitialize() or OleInitialize(), respectively. <b>When this call is made, the OS creates a hidden top-level window, owned by your thread, for implementation purposes. Because the OS relies on Windows messaging behind-the-scenes, your thread should, and in some cases MUST, pump messages.</b> Failure to do so can result in automation errors, and sometimes in a deadlock situation." If you call the :create() method on an XbasePart window, what likely happens is that a custom message is posted to the EVM thread, requesting it to create a window of the specified class, on your behalf. The Windows message loop running within the EVM thread picks that message up and essentially causes CreateWindowEx() to be called -- <b>within the EVM thread context.</b> (Steffen or Till, if you read this, please correct me if I'm mistaken.) On the other hand, if you create a window by calling CreateWindowEx() within an Xbase++ user-level thread, you implicitly also create a Windows message queue in that thread, and therefore <b>must</b> run a Windows message loop in that same thread. Failing to do so, program execution will hang sooner rather than later. When mixing XbasePart windows and native windows in the same thread, it becomes evident that Windows message loops and Xbase++ user-level event loops do not coexist very well. AppEvent() clearly does not take into account the possibility that a Windows message queue might have been created in the current thread which requires servicing. With no timeout specified, the current thread is suspended while in AppEvent(), waiting for user-level Xbase++ events to arrive, even though at the same time, lots of messages may have queued up, waiting to be handled, in the thread's local Windows message queue. One way around this is to use a timeout value for AppEvent() and poll the Windows message queue any time AppEvent() returns, or, the other way round, use the MsgWaitForMultipleObjectsEx() API function with timeout and poll the Xbase++ event queue instead, as Phil implies. Either way, the shorter the timeout interval, the more responsive the user interface, but you will see CPU load going up significantly. Alternatively, create an auxiliary thread that serves as the owner and thus message dispatcher for any native windows you create. That is, essentially, roll your own EVM thread. Looking at the Cockpit XbaseParts integration sample (CockpitLibPartsIntegration.zip) seems to indicate that this is how Michael does it. (Again, if you read this, Michael, please correct me if I'm mistaken.) Third alternative, petition AST (which I'm doing herewith) to make the user-level Xbase++ event queue alertable, so that AppEvent() returns a specified result code if there are any messages in the thread-local Windows message queue (which might exist, after all). Or, even more useful, provide a function to retrieve the handle for the (hypothetical, but fairly necessary) synchronization object which controls the user-level Xbase++ event queue internally. (Well, I havn't met that critter yet, but that seems to be the standard way of implementing event queues.) The latter would enable us to customize the Xbase++ event loop most efficiently, allowing it to spring into action on Winsock events or file-system change events as well, all without using CPU cycles while idle. In my opinion, abstraction in any framework can only go so far. The strength of any framework lies not merely in decent design tools, but in its extensibility if need arises. Finally, not really Off Topic: While perusing Larry Osterman's blog, don't miss this entry for a hilarious implementation of event processing: http://blogs.msdn.com/larryosterman/archive/2005/04/12/407628.aspx Honi soit qui mal y pense. Just my 2 cents, Günter | |
Hannes Ziegler | Re: Xbase++ 1.9 feature request on Fri, 22 Apr 2005 02:09:32 +0200 Günter, thank you for an elaborated message including very interesting links. I think all we do here is speculation on how Xbase++ sits on the OS event handling. A clarifying message of the Alaska guys could help a lot. Have you ever checked XbpPartHandler:setOwnerThread() ? (Undoced. Use :classDescribe() to find the method) The method allows for registering an XbasePart in a thread different from the creation thread. As a result, I conclude, that the XbasePart message handling is done within an abstraction layer that sits on top of the OS message handling. i.e. windows can be exchanged between threads (similarly as workareas can be exchanged between threads). FWIW, one thing that makes Xbase++ so attrctive is IMO tha fact that it does not follow the OS event handling but has built its own abstraction layer for events. It is this abstraction layer I want to register my CreateWindow() handles in. This is something we can only get from Alaska. Hence my feature request. Regards, -- Hannes > Hannes, > > unfortunately, for the EVM thread to see any messages related > to a specific window, that window <b>must have been created</b> by > the EVM thread itself. To be fair, that's just the way Windows works, > no Alaska design flaw. Messages to a window are delivered only to the > thread that created it. > > The links below do emphasize this, and also show what this implies > for hosting ActiveX controls. (That's what you're essentially driving > at, I presume.) > > + "Concurrency and Windows", by Larry Osterman > http://blogs.msdn.com/larryosterman/archive/2005/03/22/400583.aspx > > + Understanding COM Apartments, Part I & II, by Jeff Prosise > http://www.codeguru.com/Cpp/COM-Tech/activex/apts/article.php/c5529/ > http://www.codeguru.com/Cpp/COM-Tech/activex/apts/article.php/c5533/ > > + PRB: "The Remote Procedure Call Failed" During OLE Automation > http://support.microsoft.com/kb/181894/EN-US/ > > Quote from the latter: > "Every thread that uses COM or OLE must call CoInitialize() or > OleInitialize(), respectively. <b>When this call is made, the OS > creates a hidden top-level window, owned by your thread, for > implementation purposes. > Because the OS relies on Windows messaging behind-the-scenes, > your thread should, and in some cases MUST, pump messages.</b> > Failure to do so can result in automation errors, and sometimes > in a deadlock situation." > > If you call the :create() method on an XbasePart window, what likely > happens is that a custom message is posted to the EVM thread, > requesting it to create a window of the specified class, on your > behalf. The Windows message loop running within the EVM thread picks > that message up and essentially causes CreateWindowEx() to be called > -- <b>within the EVM thread context.</b> > (Steffen or Till, if you read this, please correct me if I'm > mistaken.) > > On the other hand, if you create a window by calling CreateWindowEx() > within an Xbase++ user-level thread, you implicitly also create a > Windows message queue in that thread, and therefore <b>must</b> run a > Windows message loop in that same thread. Failing to do so, program > execution will hang sooner rather than later. > > When mixing XbasePart windows and native windows in the same thread, > it becomes evident that Windows message loops and Xbase++ user-level > event loops do not coexist very well. AppEvent() clearly does not take > into account the possibility that a Windows message queue might have > been created in the current thread which requires servicing. With no > timeout specified, the current thread is suspended while in > AppEvent(), waiting for user-level Xbase++ events to arrive, > even though at the same time, lots of messages may have queued up, > waiting to be handled, in the thread's local Windows message queue. > > One way around this is to use a timeout value for AppEvent() and poll > the Windows message queue any time AppEvent() returns, or, the other > way round, use the MsgWaitForMultipleObjectsEx() API function with > timeout and poll the Xbase++ event queue instead, as Phil implies. > Either way, the shorter the timeout interval, the more responsive the > user interface, but you will see CPU load going up significantly. > > Alternatively, create an auxiliary thread that serves as the owner > and thus message dispatcher for any native windows you create. > That is, essentially, roll your own EVM thread. > Looking at the Cockpit XbaseParts integration sample > (CockpitLibPartsIntegration.zip) seems to indicate that this is > how Michael does it. (Again, if you read this, Michael, please correct > me if I'm mistaken.) > > Third alternative, petition AST (which I'm doing herewith) to make the > user-level Xbase++ event queue alertable, so that AppEvent() returns > a specified result code if there are any messages in the thread-local > Windows message queue (which might exist, after all). Or, even more > useful, provide a function to retrieve the handle for the > (hypothetical, but fairly necessary) synchronization object which > controls the user-level Xbase++ event queue internally. (Well, I > havn't met that critter yet, but that seems to be the standard way of > implementing event queues.) > > The latter would enable us to customize the Xbase++ event loop most > efficiently, allowing it to spring into action on Winsock events or > file-system change events as well, all without using CPU cycles while > idle. > > In my opinion, abstraction in any framework can only go so far. > The strength of any framework lies not merely in decent design tools, > but in its extensibility if need arises. > > Finally, not really Off Topic: While perusing Larry Osterman's blog, > don't miss this entry for a hilarious implementation of event > processing: > > http://blogs.msdn.com/larryosterman/archive/2005/04/12/407628.aspx > > Honi soit qui mal y pense. > > Just my 2 cents, > > Günter | |
Gnter Beyes | Re: Xbase++ 1.9 feature request on Fri, 22 Apr 2005 12:40:19 +0200 Hannes, > I think all we do here is speculation on how Xbase++ sits on the OS > event handling. A clarifying message of the Alaska guys could help a > lot. Yep, fully agreed. Call it "informed speculation" though. If you've got Visual C++, the Spy++ tool (spyxx.exe) shows those custom Windows messages arriving in the EVM thread, to be processed by a hidden window of class xpp_blind_message_receiver. > ... XbpPartHandler:setOwnerThread() Yes, I've noticed that method. Still, as far as I know my Windows 101, file handles (the OS entity on which the workarea construct is based) are shared by all threads of a process, thus exchanging workareas between those threads is scientifically possible. For window handles, I'm not so sure. I still refuse to believe in magic > FWIW, one thing that makes Xbase++ so attractive is IMO the fact that it > does not follow the OS event handling but has built its own abstraction > layer for events. Absolutely. > This is something we can only get from Alaska. Hence my feature request. I think we're all in the same boat here. Regards, Günter |