The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: zemtex on September 04, 2010, 06:48:37 PM

Title: The window callback function
Post by: zemtex on September 04, 2010, 06:48:37 PM
Hello.

When you use getmessage, it waits until a message is available, and then you naturally dispatch the message to the windows message handler function which you passed in the structure when you registered the window.

My question is why do we need such a function when you can handle the messages in a messageloop directly, using peekmessage? I don't get it why this function is so important. I find myself handling some important messages just beneath the peekmessage call and the rest in the callback function, it seems rather messy. Can anyone explain the purpose of that callback function?

EDIT: I think I got the answer with a little bit of thinking. Perhaps its important to get messages right there when they are available? Important messages may need instant handling? (But then again, thats nothing you cant do in a loop or just beneath getmessage or peekmessage)
Title: Re: The window callback function
Post by: xandaz on September 04, 2010, 07:28:48 PM
    Would it work if you didnt mention lpfnWndProc in WNDCLASSEX? Well, i think you'll need to accept the fact that windows is designed this way. I'm with you all the way i think. It's not a very programmer friendly platform, but hey, there's even more confusing things than that. So bare with it.
   Courage zemtex.
   Bye
Title: Re: The window callback function
Post by: baltoro on September 04, 2010, 08:38:32 PM
Raymond Chen has a number of blog entries detailing the common mistakes that programmers make in their message loops (http://blogs.msdn.com/b/oldnewthing/archive/2005/04.aspx?PageIndex=1). It's a two page monthly listing,... you have to scroll through the stuff that doesn't apply.
The MSDN page that explains Using Messages and Message Queues (http://msdn.microsoft.com/en-us/library/ms644928) also has lots of information.
Quote from: MSDNYou can use the PeekMessage function to examine a message queue during a lengthy operation. PeekMessage is similar to the GetMessage function; both check a message queue for a message that matches the filter criteria and then copy the message to an MSG structure. The main difference between the two functions is that GetMessage does not return until a message matching the filter criteria is placed in the queue, whereas PeekMessage returns immediately regardless of whether a message is in the queue.
Title: Re: The window callback function
Post by: redskull on September 04, 2010, 10:17:23 PM
Message queues are associated with a particular thread, and a particular thread may create any number of Windows.  With your method, it would require parsing the returned message to figure out which window it was destined for, and then having logic within each message type for each window; a programming nightmare.  For example

PeekMessage()
if message = Click
    if Window = a
         Do_Something_on_Window_A
    if Window = b
         Do_Something_on_Window_B
if message = Key
   if Window = a
         Do_Something_Else_on_Window_A
    if Window = b
         Do_Something_Else_on_Window_B     



Now scale that to 50, and you can see the problem.  With the current way, each window has it's own, encapsulated procedure, and only has to worry about messages destined for it.

-r
Title: Re: The window callback function
Post by: lingo on September 05, 2010, 12:44:10 AM
zemtex,
Congratulations about "non-standard" thinking but it is very old "invention" (see the link) :green

redskull is right about different windows but don't worry
coz you will not use two slow API's - TranslateMessage and DispatchMessage
and you have a lot of time in the main loop to create the logic about each message type for each window...
It is not mandatory to have main AND callback functions too. 
So, you can work with EBX,EBP,ESI and EDI registers without preservation too,
coz you have main proc only (and it is not a callback proc).

I just did a copy of the old example from link (http://www.asmcommunity.net/board/index.php?topic=5702.30) :U

.386                          ; minimum processor needed for 32 bit
      .model flat, stdcall    ; FLAT memory model & STDCALL calling
      option casemap :none    ; set code to case sensitive

      include \masm32\include\windows.inc
      include \masm32\include\user32.inc
      include \masm32\include\gdi32.inc
      include \masm32\include\kernel32.inc
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\kernel32.lib

.data
szDisplayName db "Test",0
szClassName   db "Test_Class",0
szTest                    db "I don't want to feel guilty if my programs"
                          db " don't start with :",13,10
                          db " Start:",13,10
                          db "            invoke  GetModuleHandle,NULL",10,13
                          db "            mov     hInstance, eax",10,13
                          db "            invoke  WinMain,eax,0,0,0",10,13
                          db "            invoke  ExitProcess,eax",10,13
                          db " END Start",0
szConfirm                 db "Please Confirm Exit",0
wc     WNDCLASSEX  <sizeof WNDCLASSEX, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW, \
                    offset WndProc, 0, 0,0,0,0,COLOR_WINDOW +1, 0, szClassName, 0>
.data?
hWnd           dd  ?
dStack         dd  ?   
ps             PAINTSTRUCT  <?>
rect           RECT  <?>

.code
start:
mov         esi, 0FFFF0000h
mov         dStack, esp             ; save the stack
and         esi, $        ; esi->instance handle
invoke      LoadIcon, 0, IDI_APPLICATION
mov         wc.hIcon, eax
invoke      LoadCursor, 0,IDC_ARROW
mov         wc.hCursor, eax
mov         wc.hInstance, esi   ; esi->instance handle
invoke      RegisterClassEx, addr wc
invoke      CreateWindowEx, WS_EX_OVERLAPPEDWINDOW,
                 addr szClassName,
                 addr szDisplayName,
                 WS_OVERLAPPEDWINDOW or WS_VISIBLE,
                 100,100,500,350,
                 0, 0, esi, 0   ; esi->instance handle
;...............................................;
WndProc:                   
               cmp esp, dStack       
               je  WinGetMessage   
WinMain:                   
               mov  eax, [esp+2*4]      ; eax->uMsg
               mov  esi, [esp+1*4]      ; esi->hwnd
               cmp  eax,WM_CLOSE 
               je   OnDestroy       
               cmp  eax, WM_PAINT 
               je   OnPaint           
               cmp  eax, WM_CREATE 
               jne  DefWindowProc  ;  call API
;...................................................................;
OnCreate:                                     
         mov   hWnd, esi                           
         jmp    DefWindowProc                     
;...................................................................;
OnPaint:                                         
        invoke BeginPaint, esi, ADDR ps
        mov    edi, eax                        ; edi->hDC
        invoke GetClientRect, esi, addr rect
        invoke DrawText, edi, addr szTest,-1,\ ; edi->hDC
                              addr rect, DT_VCENTER     
        invoke EndPaint, esi, addr ps         
        jmp    DefWindowProc     ;  call API
;...................................................................;
OnDestroy:                                 
              invoke MessageBox, esi, \     
              addr szConfirm, \                 
              addr szDisplayName,\         
              MB_YESNO                       
              cmp  eax, IDNO     
              jne    ExitProcess              ; Exit
;...................................................................;
             mov  esp, dStack       
WinGetMessage:           
             lea eax, [esp-4*4]           
             mov [esp-5*4], offset WndProc          ; return address -> WndProc
             mov dword ptr [esp-6*4], 0             ; zeros are parameters
             mov dword ptr [esp-7*4], 0             ; of GetMessage
             mov dword ptr [esp-8*4], 0                 
             mov [esp-9*4], eax                     ; eax-> offset MSG struct
             mov [esp-10*4], offset WinMain         ; return-> WinMain
             sub  esp, 10*4                               
             jmp  GetMessage                        ; call API
;...................................................................;
end  start

Title: Re: The window callback function
Post by: zemtex on September 05, 2010, 10:11:24 AM
Anyway, I always use GetQueueStatus for quick hint if there is messages available before i pass the execution to the slow (5 push) peekmessage function. GetQueueStatus only has 1 push and it checks a few flags. If the message loop runs 1 million times in 10 ms, that means peekmessage is pushing and popping 5 million times (Thats alot of memory reading) Microsoft SDK also mentions that getqueuestatus is the fastest possible way to check if there are available messages.
Title: Re: The window callback function
Post by: qWord on September 05, 2010, 11:03:50 AM
zemtex,
you are worrying about about some push's while calling API-functions that end up in an syscall :P
Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 10:55:19 AM
Quote from: qWord on September 05, 2010, 11:03:50 AM
zemtex,
you are worrying about about some push's while calling API-functions that end up in an syscall :P

Microsoft says its faster, you reduce overhead in the message loop. if you produce inputs, one every 50,000 iterations, lets say by a keystroke, you would have avvoided peekmessage for 50,000 iterations. peekmessage pushes 20 bytes of data per iteration and performs a long execution afterwards to filter messages, remove unwanted messages, fill inn the msg structure. When you use getqueuestatus you push 4 bytes of data and the system checks a few flags and returns. Thats much faster.

Syscall or no syscall. If the syscall have a delay of 10 ms, that doesnt matter because you would have to substitute the delay of the message function and you get a lower overhead no matter how intensive the syscall is. This is simple math.  :U
Title: Re: The window callback function
Post by: MichaelW on September 06, 2010, 06:16:35 PM
Quote from: zemtex on September 06, 2010, 10:55:19 AM
Microsoft says its faster, you reduce overhead in the message loop. if you produce inputs, one every 50,000 iterations, lets say by a keystroke, you would have avvoided peekmessage for 50,000 iterations. peekmessage pushes 20 bytes of data per iteration and performs a long execution afterwards to filter messages, remove unwanted messages, fill inn the msg structure. When you use getqueuestatus you push 4 bytes of data and the system checks a few flags and returns. Thats much faster.

Syscall or no syscall. If the syscall have a delay of 10 ms, that doesnt matter because you would have to substitute the delay of the message function and you get a lower overhead no matter how intensive the syscall is. This is simple math.  :U

I was going to point out that when there are messages a message loop that calls GetQueueStatus and PeekMessage actually has higher overhead, but now that I test, at least on my Windows 2000 system GetQueueStatus is much slower than PeekMessage even when there are no messages. Specifically, a million loops of the message loop took ~1140ms when the loop called GetQueueStatus(QS_ALLINPUT), or ~140ms when it did not.


;==============================================================================
; Build as a console app.
;==============================================================================

;----------------------------------------------------------------------------
; This macro more or less duplicates the functionality of the BASIC language
; TIMER function, returning the elapsed seconds since the system was started
; as a floating-point value at the top of the FPU stack. The elapsed seconds
; are derived from the high-resolution performance counter, so the effective
; resolution is on the order of a few microseconds.
;----------------------------------------------------------------------------

timer MACRO
    IFNDEF _timer_pc_frequency_
        .data
            align 8
            _timer_pc_frequency_      dq 0
            _timer_pc_count_          dq 0
            _timer_elapsed_seconds_   dq 0
            _timer_initialized_       dd 0
        .code
    ENDIF
    .IF _timer_initialized_ == 0
        invoke QueryPerformanceFrequency, ADDR _timer_pc_frequency_
        inc _timer_initialized_
    .ENDIF
    invoke QueryPerformanceCounter, ADDR _timer_pc_count_
    fild _timer_pc_count_
    fild _timer_pc_frequency_
    fdiv
    fstp _timer_elapsed_seconds_
    EXITM <_timer_elapsed_seconds_>
ENDM

;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
    .data
        hInstance dd    0
        hDlg      dd    0
        loopcount dd    0
        pmcount   dd    0
        gqscount  dd    0
        time      REAL8 ?
        seconds   REAL8 ?
        msg       MSG   <>
    .code
;==============================================================================

DialogProc proc hwndDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

    SWITCH uMsg

      CASE WM_CLOSE

        invoke DestroyWindow, hwndDlg

      CASE WM_DESTROY

        invoke PostQuitMessage, NULL

    ENDSW

    xor eax, eax
    ret

DialogProc endp

;==============================================================================
start:
;==============================================================================
    invoke GetModuleHandle, NULL
    mov hInstance, eax
    Dialog 0, \
           "FixedSys",11, \
           WS_VISIBLE or WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
           0, \
           0,0,50,40, \
           1024
    CallModelessDialog hInstance, 0, DialogProc, NULL
    mov hDlg, eax
    fld timer()
    fstp time
  msgLoop:
    inc loopcount
    .IF loopcount > 1000000
        ;--------------------------------------------------------
        ; Calc and display the elapsed seconds for 1000000loops,
        ; along with the message counts.
        ;--------------------------------------------------------
        fld time
        fld timer()
        fst time
        fsubr
        fstp seconds
        invoke crt_printf, cfm$("%f\t%d\t%d\n"), seconds, pmcount, gqscount
        mov loopcount, 0
        mov pmcount, 0
        mov gqscount, 0
    .ENDIF

    IncludeGetQueueStatus equ 1

IFDEF IncludeGetQueueStatus
    invoke GetQueueStatus, QS_ALLINPUT
    .IF eax
        inc gqscount
ENDIF
        invoke PeekMessage, ADDR msg, NULL, 0, 0, PM_REMOVE
        .IF eax != 0
            inc pmcount
            .IF msg.message == WM_QUIT
                invoke ExitProcess, 0
            .ENDIF
            invoke TranslateMessage, ADDR msg
            invoke DispatchMessage, ADDR msg
        .ENDIF
IFDEF IncludeGetQueueStatus
    .ENDIF
ENDIF
    jmp msgLoop
;==============================================================================
end start


Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 06:44:20 PM
Quote from: MichaelW on September 06, 2010, 06:16:35 PM
I was going to point out that when there are messages a message loop that calls GetQueueStatus and PeekMessage actually has higher overhead, but now that I test, at least on my Windows 2000 system GetQueueStatus is much slower than PeekMessage even when there are no messages. Specifically, a million loops of the message loop took ~1140ms when the loop called GetQueueStatus(QS_ALLINPUT), or ~140ms when it did not.


All I can say is microsofts own words: "GetQueueStatus returns an array of flags that indicates the types of messages in the queue; using it is the fastest way to discover whether the queue contains any messages."

And also, keep in mind that if your message queue is always filled up, you are basically running getqueuestatus and peekmessage both at the same time per message. The getqueuestatus is really only fastest if it is used a single time or if there are few messages available. You have to weight it and see which option is better based on what program you have.

If your program is always having messages it just might be that you would do better with dropping getqueuestatus entirely.  :U

EDIT: It might be that what microsoft means by "fastest way" is that its the most easy function call to "USE", and that its not actualyl the fastest in execution. I can't really tell. The timing was interesting though. Try to run it a few more times and see if it is consistent.
Title: Re: The window callback function
Post by: MichaelW on September 06, 2010, 07:04:19 PM
Test it. The speed difference exists whether there are messages or not. Unless I intentionally trigger messages by pressing keys when the window has the focus, moving the mouse within the window, moving the window, etc, then there are no messages. I would be interested to see the timings for Windows XP and later.
Title: Re: The window callback function
Post by: oex on September 06, 2010, 07:25:05 PM
Windows XP:

IncludeGetQueueStatus equ 1
0.282236        14      1
0.284462        21      2
0.291163        11      1
0.281626        0       0
0.276215        0       0
0.271831        0       0
0.285561        0       0
0.275448        0       0
0.277165        0       0
0.275120        0       0
0.281987        0       0
0.277742        0       0
0.279168        0       0
0.282788        0       0
0.274141        0       0

IncludeGetQueueStatus equ 0
0.297155        10      11
0.269335        24      24
0.280158        12      12
0.258623        0       0
0.260007        0       0
0.253857        0       0
0.267360        0       0
0.271125        0       0
0.252812        0       0
0.265616        0       0
0.271749        0       0
0.255088        0       0
0.260941        0       0
0.260837        0       0
0.271073        0       0
Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 07:28:27 PM
On my computer with Windows 7 the getqueuestatus runs with numbers like 0.22 most of the time, and peekmessage runs with 0.23-24 most of the time when there is 0 messages available in the queue.

When there was the same amount messages available, getqueuestatus ran with 0.231 and peekmessage run slightly slower at 0.239

I DONT KNOW GUYS, what do you think. Should this method be expelled or what? You guys deside.  :cheekygreen:
Title: Re: The window callback function
Post by: MichaelW on September 06, 2010, 08:00:28 PM
I see now that I should have used a different way of controlling the conditional assembly. Because I'm testing with IFDEF, the GetQueueStatus code will be included if IncludeGetQueueStatus is defined, whatever the value assigned to it. I intended that the entire statement be commented out to remove the GetQueueStatus code. To use it the way that my equate value suggests it should be used, the:

IFDEF IncludeGetQueueStatus

statement should be:

IF IncludeGetQueueStatus EQ 1
Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 08:19:46 PM
You would also have to remove peekmessage to time both of them individually. You include peekmessage when getqueuestatus runs. You increase gqscount but the incresage will be wrong because it waits until peekmessage increases too, the timing will be wrong.
Title: Re: The window callback function
Post by: oex on September 06, 2010, 08:36:54 PM
Quote from: MichaelW on September 06, 2010, 08:00:28 PM
I see now that I should have used a different way of controlling the conditional assembly.

:lol I thought I saw a bug in my interpretation but I couldnt find it

Quote from: zemtex on September 06, 2010, 08:19:46 PM
You would also have to remove peekmessage to time both of them individually. You include peekmessage when getqueuestatus runs. You increase gqscount but the incresage will be wrong because it waits until peekmessage increases too, the timing will be wrong.

This only happens a maximum of 20/100,000 times it wont addmuch weight to the result


My new results (commenting instead of 0ing) are much different.... When commented my results are....


0.048902        34      0
0.031764        0       0
0.057923        11      0
0.053695        0       0
0.030719        0       0
0.028572        0       0
0.034822        1       0
0.030796        0       0
0.028341        0       0
0.027664        0       0
0.040897        0       0
0.027688        0       0
0.027359        0       0
0.029990        0       0
0.035721        0       0


(10 times faster without GetQueueStatus)
Title: Re: The window callback function
Post by: redskull on September 06, 2010, 08:41:48 PM
Quote from: zemtex on September 06, 2010, 07:28:27 PM
Should this method be expelled or what? You guys deside.  :cheekygreen:

The better question is why use a non-blocking version in the first place?  Unless you are writing something like a game that must "run all the time", spinning your wheels checking for non-existant messages is a waste of the CPU.

-r
Title: Re: The window callback function
Post by: MichaelW on September 06, 2010, 08:47:02 PM
Quote from: zemtex on September 06, 2010, 08:19:46 PM
You would also have to remove peekmessage to time both of them individually. You include peekmessage when getqueuestatus runs. You increase gqscount but the incresage will be wrong because it waits until peekmessage increases too, the timing will be wrong.

What would be the point of timing GetQueueStatus separately, when it is not intended for freestanding use? I was attempting to time what I thought you were describing, and expecting different results than what I got. On my system the combination of GetQueueStatus and PeekMessage is ~8 times slower than PeekMessage alone. I use gqscount to track the number of times per timed interval that GetQueueStatus indicates one or more messages in the queue, and pmcount to track the number of times per timed interval that PeekMessage returns a message. Neither of these values have anything to do with the computation of the timed interval.
Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 08:55:33 PM
Quote from: MichaelW on September 06, 2010, 08:47:02 PM
What would be the point of timing GetQueueStatus separately, when it is not intended for freestanding use?

If you are timing (A+B) against (A) then there is no point to remove it. However, if you intend to use getqueuestatus to run 100,000 times when there are no messages, it is relevant because you would be stuck with no messages for 100,000 iterations.  :wink
Title: Re: The window callback function
Post by: MichaelW on September 06, 2010, 09:00:42 PM
Quote from: redskull on September 06, 2010, 08:41:48 PM
The better question is why use a non-blocking version in the first place?  Unless you are writing something like a game that must "run all the time", spinning your wheels checking for non-existant messages is a waste of the CPU.

Yes, the difference in CPU utilization is large. If I comment out the display code to prevent it from further loading the CPU, I get essentially a 100% utilization for the non-blocking loop, and 0 to ~10% utilization (depending on the number of messages being queued) for the blocking loop.
Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 09:09:53 PM
Quote from: MichaelW on September 06, 2010, 09:00:42 PM
Quote from: redskull on September 06, 2010, 08:41:48 PM
The better question is why use a non-blocking version in the first place?  Unless you are writing something like a game that must "run all the time", spinning your wheels checking for non-existant messages is a waste of the CPU.

Yes, the difference in CPU utilization is large. If I comment out the display code to prevent it from further loading the CPU, I get essentially a 100% utilization for the non-blocking loop, and 0 to ~10% utilization (depending on the number of messages being queued) for the blocking loop.


May I also suggest you dont use PM_REMOVE as when getqueuestatus runs, it doesnt remove the messages, but it does in peekmessage. When you're done, report the numbers back to me again  :U
Title: Re: The window callback function
Post by: MichaelW on September 06, 2010, 09:17:39 PM
Quote from: zemtex on September 06, 2010, 08:55:33 PM
If you are timing (A+B) against (A) then there is no point to remove it. However, if you intend to use getqueuestatus to run 100,000 times when there are no messages, it is relevant because you would be stuck with no messages for 100,000 iterations.  :wink

PeekMessage and everything below it runs only if GetQueueStatus returns non-zero, so in the absence of messages GetQueueStatus is being called a million times per timed interval, and PeekMessage is being called zero times. If I comment out the PeekMessage call and the IF block below it, there is essentially no change in the timings. Your idea of using GetQueueStatus to test for messages was good, but it turns out that GetQueueStatus is just too slow to be useful for this.
Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 09:19:58 PM
Quote from: MichaelW on September 06, 2010, 09:17:39 PM
Quote from: zemtex on September 06, 2010, 08:55:33 PM
If you are timing (A+B) against (A) then there is no point to remove it. However, if you intend to use getqueuestatus to run 100,000 times when there are no messages, it is relevant because you would be stuck with no messages for 100,000 iterations.  :wink

PeekMessage and everything below it runs only if GetQueueStatus returns non-zero, so in the absence of messages GetQueueStatus is being called a million times per timed interval, and PeekMessage is being called zero times. If I comment out the PeekMessage call and the IF block below it, there is essentially no change in the timings. Your idea of using GetQueueStatus to test for messages was good, but it turns out that GetQueueStatus is just too slow to be useful for this.

Replace PM_REMOVE with PM_NOREMOVE and report the numbers back to me again  :U

Change 2 I want you to do as well: Run the peekmessage in a while loop until the message buffer is emptied.
Title: Re: The window callback function
Post by: MichaelW on September 06, 2010, 09:27:04 PM
Quote
Replace PM_REMOVE with PM_NOREMOVE and report the numbers back to me again  :U

I had already tested that and there was no change in the timings that I could see, but it's not really meaningful because then you have a non-functional message loop. For the blocking loop in my test above I used GetMessage.

Title: Re: The window callback function
Post by: zemtex on September 06, 2010, 09:28:44 PM
Quote from: MichaelW on September 06, 2010, 09:27:04 PM
Quote
Replace PM_REMOVE with PM_NOREMOVE and report the numbers back to me again  :U

I had already tested that and there was no change in the timings that I could see, but it's not really meaningful because then you have a non-functional message loop. For the blocking loop in my test above I used GetMessage.


It makes all the difference. You get second delays when you replace it. GetQueueStatus is way faster here. And if you run that loop in a true program, you will miss alot of messages if the traffic is heavy because you dont use a while loop.

I hope you see the difference. GetQueueStatus does not remove the message, but peekmessage does, so only the very first iteration is qualified to time the two functions. (UNLESS you are willing to replace PM_REMOVE with PM_NOREMOVE, if you do that you will discover huge delays using peekmessage)
Title: Re: The window callback function
Post by: MichaelW on September 07, 2010, 01:26:33 AM
Quote from: zemtex on September 06, 2010, 09:28:44 PM
It makes all the difference. You get second delays when you replace it. GetQueueStatus is way faster here. And if you run that loop in a true program, you will miss alot of messages if the traffic is heavy because you dont use a while loop.

I hope you see the difference. GetQueueStatus does not remove the message, but peekmessage does, so only the very first iteration is qualified to time the two functions. (UNLESS you are willing to replace PM_REMOVE with PM_NOREMOVE, if you do that you will discover huge delays using peekmessage)

I have no idea what you mean. If there is a valid point buried in there some where, post code that demonstrates it.

Title: Re: The window callback function
Post by: zemtex on September 07, 2010, 06:56:10 AM
Quote from: MichaelW on September 07, 2010, 01:26:33 AM
Quote from: zemtex on September 06, 2010, 09:28:44 PM
It makes all the difference. You get second delays when you replace it. GetQueueStatus is way faster here. And if you run that loop in a true program, you will miss alot of messages if the traffic is heavy because you dont use a while loop.

I hope you see the difference. GetQueueStatus does not remove the message, but peekmessage does, so only the very first iteration is qualified to time the two functions. (UNLESS you are willing to replace PM_REMOVE with PM_NOREMOVE, if you do that you will discover huge delays using peekmessage)

I have no idea what you mean. If there is a valid point buried in there some where, post code that demonstrates it.

What you seem not to understand is that peekmessage removes the message and runs 99.9% with an empty message queue, while getquestatus runs with a full message queue all the time when you should have emptied it when it discover a message.

Replace PM_REMOVE with PM_NOREMOVE and report the numbers back again. Copy the numbers and report them in again.  :cheekygreen:

Here is from your code: invoke PeekMessage, ADDR msg, NULL, 0, 0, PM_REMOVE
Replace the last argument with PM_NOREMOVE. (tip for you)

Here is your real numbers: (http://i54.tinypic.com/2yke3j6.png)
About 5 times slower than GetQueueStatus. (OFFTopic joke: Whats funny about that is that peekmessage also uses 5 times the amount of arguments  :lol)
Title: Re: The window callback function
Post by: MichaelW on September 07, 2010, 04:18:50 PM
QuoteWhat you seem not to understand is that peekmessage removes the message and runs 99.9% with an empty message queue, while getquestatus runs with a full message queue all the time when you should have emptied it when it discover a message.

I understand what PeekMessage does. My code removes the messages, whether it's configured to run PeekMessage alone, or run PeekMessage after GetQueueStatus indicates that there are messages in the queue. It does what you describe here:

Quote from: zemtex on September 05, 2010, 10:11:24 AM
Anyway, I always use GetQueueStatus for quick hint if there is messages available before i pass the execution to the slow (5 push) peekmessage function. GetQueueStatus only has 1 push and it checks a few flags. If the message loop runs 1 million times in 10 ms, that means peekmessage is pushing and popping 5 million times (Thats alot of memory reading) Microsoft SDK also mentions that getqueuestatus is the fastest possible way to check if there are available messages.

And the results show that GetQueueStatus slows the message loop down. There is no point in testing GetQueueStatus alone because it will not be used alone. There is no point in testing PeekMessage with PM_NOREMOVE because without some way to remove the messages, the message loop and application will not function correctly.

Here is a sampling of my results without the GetQueueStatus code:

0.140525        13      0
0.140405        14      0
0.140311        8       0
0.140667        13      0
0.139825        7       0
0.140351        9       0
0.139806        0       0
0.140035        0       0
0.139867        0       0
0.140347        0       0

And a sampling with the GetQueueStatus code:

1.142921        9       9
1.140578        0       0
1.140418        6       6
1.138636        15      15
1.143593        3       3
1.144531        0       0
1.137575        0       0
1.143059        0       0
1.140317        0       0
1.142379        0       0


I'm done here.

Title: Re: The window callback function
Post by: zemtex on September 07, 2010, 05:01:19 PM
Quote from: MichaelW on September 07, 2010, 04:18:50 PM
QuoteWhat you seem not to understand is that peekmessage removes the message and runs 99.9% with an empty message queue, while getquestatus runs with a full message queue all the time when you should have emptied it when it discover a message.

I understand what PeekMessage does. My code removes the messages, whether it's configured to run PeekMessage alone, or run PeekMessage after GetQueueStatus indicates that there are messages in the queue. It does what you describe here:

You forgot the while loop my man, you forgot the while loop.  :bdg

Quote from: MichaelW on September 07, 2010, 04:18:50 PM
And the results show that GetQueueStatus slows the message loop down. There is no point in testing GetQueueStatus alone because it will not be used alone. There is no point in testing PeekMessage with PM_NOREMOVE because without some way to remove the messages, the message loop and application will not function correctly.

There is nothing that forces you to use peekmessage, keep in mind the different filters available to getqueuestatus. And its twin-cousin getinputstatus can be used effectively in combinations as well.

The point of using PM_NOREMOVE is to test the individual functions up against each other. Peekmessage have an "exit strategy" in your 1 million time iteration loop. GetQueueStatus has no "exit strategy". Once peekmessage discovers a message it removes it instantly while GetQueueStatus is not able to do that while in a real program GetQueueStatus would not be stuck in such a position to not be able to do that and PeekMessage would never run once with an empty buffer.

GetQueueStatus is much faster in checking a message buffer than what peekmessage is. And this proves my point and microsoft as well that GetQueueStatus is faster, but you have to be careful where you use it. Bad implementation is your own responsibility.

One usage could be to run GetQueueStatus once per second and then run PeekMessage in a while loop.
Another usage could be to look for paint messages, which would be too time consuming to do in peekmessage.

Whatever the usage is, as long as it gives positive progress in the program, it should be used.
I'm out of here myself.
Quote