Greedy Message Loop
Some people (notably game programmers) want to do some background
processing when there are no messages to process. For them, we
show a "greedy" message loop. Instead of giving up the time
slice, we use as much of it as we can by replacing GetMessage
with PeekMessage.
.data
msgbuf MSG <>
.code
call setup
msg_loop:
push large PM_REMOVE
push large 0 ; uMsgFilterMax
push large 0 ; uMsgFilterMin
push large 0 ; hWnd (filter), 0 = all windows
push offset msgbuf ; lpMsg
call PeekMessage ; returns nonzero (true) if there's a message
or eax,eax
jnz got_msg
call do_background_process
jmp msg_loop
got_msg:
cmp msgbuf.msg_message,WM_QUIT
je end_msg_loop
call dispatch_message
jmp msg_loop
end_msg_loop:
call cleanup
The above code is extremely greedy. It will use up time if there
is no background processing to do. It will also use up time when
no windows are being displayed. Because of preemption, we do not
prevent other programs from running. But because we are using our
entire time slice, we are slowing them down.
The less greedy version, below, uses a flag to signal an
active, greedy state. The flag can be switched by a message
handler.
ACTIVE_FLAG equ 1
.data
flags dd ACTIVE_FLAG
msgbuf MSG <>
.code
call setup
msg_loop:
test flags,ACTIVE_FLAG ; are we active ?
jz get_next_msg ; no, don't be greedy
push large PM_NOREMOVE ; ***** LEAVE MESSAGE IN QUEUE *****
push large 0 ; uMsgFilterMax
push large 0 ; uMsgFilterMin
push large 0 ; hWnd (filter), 0 = all windows
push offset msgbuf ; lpMsg
call PeekMessage ; returns nonzero (true) if there's a message
or eax,eax
jnz get_next_msg
call do_background_process
jmp msg_loop
get_next_msg:
push large 0 ; uMsgFilterMax
push large 0 ; uMsgFilterMin
push large 0 ; hWnd (filter), 0 = all windows
push offset msgbuf ; lpMsg
call GetMessage ; returns FALSE if message is WM_QUIT
or eax,eax
jz end_msg_loop
call dispatch_message
jmp msg_loop
end_msg_loop:
call cleanup