The attached program is an example I have had in mind for a while to test out a different message dispatching architecture in a Windows GUI application.

It carries the overhead of a 4k array but once loaded, it will branch to any message in 2 assembler instructions, no matter how many messages there are to process. It also simplifies the WndProc by removing the large switch block associated with normal Wndproc message processing.

The catches are these, every message you wish to process must be added to the array, (a macro is provided to do this) and if you wish to use private messages that can range in value to 0FFFFh, you must make the array size 65536 which is 256k of memory.

I don't know if its an original idea but in performance terms for branching, it will rip the titz off anything else I have seen.

Regards,

hutch@movsd.com
Posted on 2002-11-30 02:15:20 by hutch--
it will rip the titz off anything else I have seen.
LMAO! :grin: is this suppose to be a figure of speech or should I take it literally? :stupid:
Posted on 2002-11-30 02:34:06 by stryker
I'm impressed, this kind of message dispatcher would make great in an app where time is limited (eg games)...
I think you're the first that's implented it, but I'm sure others have scratched the surface of the idea but never given it any depper thoughts (or trying to code it), untill you made the working example. :)

it will rip the titz off anything else I have seen.

I just heard a scream... ;)

I just implented the "Hutch Fast Message Dispatch Algorithm" (:) ) into an application (sill pre-alpha, thus in the phase where bugs are written ;) ) and, the message dispatching works flawless... :)
Posted on 2002-11-30 03:43:01 by scientica
it will rip the titz off anything else I have seen.

LMAO! is this suppose to be a figure of speech or should I take it literally?
I just heard a scream...


LOL. Too funny. Still cant stop laughing. :grin:

Btw, Stryker whats the full form of LMAO and also IIRC. I seen that in quite a few places too.

Anyway nice work hutch :)
Posted on 2002-11-30 09:25:37 by clippy


Btw, Stryker whats the full form of LMAO and also IIRC. I seen that in quite a few places too.


www.acronymfinder.com
Posted on 2002-11-30 09:28:27 by bazik
nice link Bazik.

Btw hutch,
What are 'global' labels? And how are they different from local labels?
Posted on 2002-11-30 10:26:52 by clippy
I found this in my HutchOutgoing Directory of March 2000. Not high speed but ....


James
Posted on 2002-11-30 11:59:32 by jcfuller
James,

I confess I have on and off chewed over you idea for a couple of years and while I don't think this one fully enacts your design for proper encapsulation of each message I think it can be done if you want to manage the stack so that the parameters are passed along with it to the designated procedure for each message.

I just don't see a way around the global scope labels but then this may not be a problem with your basic design anyway as the code to place the label addresses into the array only needs to be within the same module and the labels are not accessed from outside the WndProc while the app is running normally.

Josh,

"rip the titz off". Idiom does not always translate well but I will try.

When something goes past a bit faster, it may be noticed. When it goes past a fair bit faster it will cause a breeze. When it goes past a lot faster it may leave their titz in a tangle but when it goes past so much faster, it just rips the titz off them. :tongue:

Regards,

hutch@movsd.com
Posted on 2002-11-30 17:10:00 by hutch--
Sound soooo Gooood

"goes past so much faster" .... When the Flag Drop ____
Posted on 2002-11-30 20:16:11 by cmax
Something i don't want to get an Mis-Understanding about...

What do you hutch.. mean by private messages... It's just like for a long time I thought virtural protect mean protect your app but come to find out it was only vesa-versa. Private message sound like it should not be easy seen by other app's or the OS itself. Is this true.

Posted on 2002-11-30 21:31:43 by cmax
I think he means application-defined messages.
Posted on 2002-11-30 23:25:19 by iblis
Nice example Hutch,

"High speed message dispatcher"

pls correct me if I'm wrong, but you use the standard message dispatch loop
with GetMessage(), TranslateMessage() and DispatchMessage()
When the DispatchMessage() dispatch the message to WndProc you
execute correct procedure using mov eax, uMsg / jmp DWORD PTR

The idea is not new, (see ASM journal) but I'm wondering
why the title is "High speed message dispatcher"
I saw similar new idea in an example here: http://www.asmcommunity.net/board/showthread.php?threadid=5702&highlight=BuliaNaza
and learned how to get the message and execute the correct procedure
DIRECTLY without DispatchMessage(), i.e. skip not only one Windows API
but to reduce the messages traffic also

May be I'm wrong (pls, correct me) but for me it is a
"High speed message dispatcher" because understood his/her new idea:
"after GetMessage(), the message is here in the main message loop,
and we can execute DIRECTLY the correct procedure without ANY dispatching,
or it is a waste of time and recourses to dispatch the message again to Windows
with DispatchMessage() and to receive the same message again later from
Windows in WndProc"

"This example allocates an array in the uninitialised DATA SECTION..."

I'm wondering why you do that ...just use the stack, and why
you continue to use .if .elseif .elseif .endif with WM_COMMAND messages


Thanks again for posting,


Regards,
Lingo
Posted on 2002-12-01 01:14:20 by lingo12
lingo12,

I have seen various attempts to bypass the Wndproc and dispatch messages directly from the message loop but I have yet to see one that is reliable and extendable and works on all windows versions.

The API calls in the message loop are OS defined and the location for the dispatched messages from the message loop is again OS defined in the WNDCLASSEX structure so I have yet to see an advantage in deviating from this.

Now in regard to you suggestion and following question,

"This example allocates an array in the uninitialised DATA SECTION..."

I'm wondering why you do that ...just use the stack,

The addresses to dispatch to still must be loaded and doing this on the stack each time a message is passed to the location defined in the WNDCLASSEX structure would be really slow. Using the uninitialised data section only has to be done once as it has GLOBAL scope.

and why you continue to use .if .elseif .elseif .endif with WM_COMMAND messages

I modified one of my standard templates which used the .if block syntax as I was writing an example for branching in the WndProc procedure. It is possible to do the same for any collections of branches that may impinge on performance but I doubt that 3 branch testing is a performance problem.

The example does what it is supposed to do, it branches to any message in the WndProc in 2 instructions and it is a variation of a branching technique that is generally known as a dispatcher, the difference is that it is a lot faster than a list of comparisons.

Regards,

hutch@movsd.com
Posted on 2002-12-01 02:14:23 by hutch--
:alright: I've known it was possible to do it this way, but have never needed the raw speed enough to justify the code bloat.
Posted on 2002-12-01 03:09:16 by tenkey
Hutch,

"The API calls in the message loop are OS defined.."

I agree, in Basic and high level languages with hidden message loop,
but in assembly we have not a canon , i.e. in message loop we can
mix our code and freely chosen by US "OS defined API" without "OS defined" restrictions..


"The addresses to dispatch to still must be loaded and doing this on the stack each time a message
is passed to the location defined in the WNDCLASSEX structure would be really slow. Using the
uninitialised data section only has to be done once as it has GLOBAL scope."

Why each time?
In assembly we have a freedom to work with "non balanced" stack and we can do:


.data?
; wMsgs dd asize dup (?) ; save space!!!
hInstance dd ?
.....
.....
.code
start:
lea eax, [esp- asize*4] ; room for table with addresses
mov esp, eax ; where asize->array item count
invoke InitMsgArray
invoke InitCommonControls
.....
.....
; in the end of program we can balance the stack
.......
lea esp, [esp+asize*4]
invoke ExitProcess, eax

InitMsgArray proc
; ---------------------------------------------------------------
; fill array with address of default processing label in WndProc
; ---------------------------------------------------------------
push edi
; mov edi, OFFSET wMsgs ; array address
mov edi, eax ; eax->array address parameter
mov eax, OFFSET DEF_MSG_HANDLER ; default processing label in WndProc
mov ecx, asize ; array item count
rep stosd
pop edi
As you see, I just add 3 new rows in your code and modify one

Regards,
Lingo
Posted on 2002-12-01 12:02:06 by lingo12
Sorry for interrupting you guys but me being pretty new to asm i cant understand this algo too well. Can somebody explain me these things-
What exactly are global variables and how are they different from local variables?
What exactly do u mean by offset?
If the array you are using stores the address of label then how is it that when you use the message as the index in the array the appropriate label comes out?
Posted on 2002-12-01 15:45:57 by clippy
gladiator,

A GLOBAL label has the :: at the end of it and it denotes that you can access the label from anywhere in the program. A local label has a single : which denotes that it can only be accessed from within the procedure it is written in. From memory there is also options to change this in MASM.

A label is only a place holder for the next instruction and that place holder is an address in memory. What the application I posted does is load the addresses into an array and at the beginning of the Wndproc, it gets the address of the label from the array and jumps to that address.

lingo12/Bulianaza,

The suggestion of using stack memory is an interesting one but you get nothing for nothing. Stack is allocated memory like any other memory and where the problem will occur with an unbalanced stack is that you lose range in the stack by amount of stack imbalance. It probably does not matter with 4k when default stack is 1 meg but try it with 256k imbalance and run highly recursive procedures and you go past the end and crash. To compensate you must allocate more stack memory to have the same range.

Uninitialised data does not have this problem and it does not make the file larger either so it is a better choice in this instance.

With message delivery, what you have defined with the OS is that messages for a window will arrive at a predefined address with 4 DWORD parameters on the stack. What you do with it is your own choice as long as you can get it to be reliable and extendable.

Regards,

hutch@movsd.com
Posted on 2002-12-01 17:53:18 by hutch--
I have modified the original file to make a version that is in the architecture type that is suitable for "event driven" programming. The original JMP had been replaced by a CALL and for each message processed, there is a seperate procedure to do it that has the 4 parameters from ther WndProc passed to it.

To do this requires 4 additional pushes for the stack parameters as they are available in the WndProc which makes the version marginally slower but it is probably not a problem in peformance terms.

It is an architecture that is suitable for a VB or a Visual Assembler style of coding where each "event" pops up in a window of its own.

The downside of this architecture if you have bad habits like I do of jumping across messages is that you lose some of you design freedom in message processing.

It has the same technical demends as the earlier version, 4k overhead for the normal messages because of the array size and if you want to process messages that you define yourself, the overhead for the array grows to 256k, a 64k DWORD array.

I think the original is the one that is the performance advantage and is more flexible while processing messages.

Regards,

hutch@movsd.com
Posted on 2002-12-02 00:35:59 by hutch--
Ok hutch, i fully understand your algo now :) A few suggestions -

if you want to process messages that you define yourself, the overhead for the array grows to 256k, a 64k DWORD array.


Instead of doing that why dont you do this-
Keep 2 arrays, one for windows defined msgs and the other for user defined msgs.
The maximum size of array of user defined msgs will obviously be know during assemble time, cause after all the user only has defined those msgs. Plus you dont need to initialize them with pointer to DefWindowProc cause if you define a msg that definetly means you are gonna implement it.

In WndProc add a check -
.IF uMsg>1024

uMsg=uMsg-1024; sutract 1024 from msg to get an index in the array for user-defined msg

this way if user defined msg was WM_USER+1 we get 1 in uMsg and now uMsg
can be used as an index for the user msgs array
.ELSE IF uMSG<=1024

;use your normal method here


this way u can keep a separate array for handling WM_COMMAND msgs too.

Btw, your algo has onemajor disadvantage. For every window or dialog that you create it has to go through a loop of 1024 to fill in the array with the pointer to DefWindowProc.

First i was thinking of not to fill the array with pointer to DefWindowProcand only fill those indexes which do have a pointer to a function. And each time a msg is to be processed do a check for 0 on the index in the array. If its not 0 that means a msg is contained there. But then i realized that instead of 0 that location may be filled with garbage value, so that would make the prog buggy.

Anyone know any way to optimize the loading of the win by somehow avoiding the loop of 1000?
Posted on 2002-12-02 06:08:06 by clippy
do you really need to push the uMsg param?

i mean, in a WM_COMMAND event, wouldn't uMsg always be WM_COMMAND...?
Posted on 2002-12-02 14:51:00 by Sloat