Alaska Software Inc. - Xbase++ 1.9 feature request
Username: Password:
AuthorTopic: 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