A TTimer with the interval set to 1 sec sends a message every 1 second. This message is processed in application's message loop, which results in the OnTimer event being triggered.
If the application is busy and doesn't have time to process the message loop, the OnTimer event is skipped.
I knwo that TTimer uses internally SetTimer.
My questions are:
Does TTimer use an internal/separate thread (via SetTimer)?
How come that the form that holds the timer (and its OnTimer even) can still do stuff if a modal MessageDlg is "blocking" the form? (see code below)
The documentations says that SetTimer requires Win2000 minimum. How was TTimer implemented in Win98?
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Caption = i;
i++;
MessageDlg(stuff); <----- we "block" application here but form's caption is still updated.
}
If the application is busy and doesn't have time to process the message loop, the OnTimer event is skipped.
That is effectively correct. This and this blog posts on MSDN give some internal implementation details, in particular they mention that an expiring timer causes the QS_TIMER flag of the message queue's state to be set. No further time lapse will cause the queue state flag to be even more set. When this flag is set and [Peek|Get]Message cannot pick any higher priority message, a timer message is generated.
Although timer messages do not pile up in the queue, it is possible to have the timer fire again while a previous event handler is executing. This is possible when the code in the handler takes longer to execute than the timer interval and re-entrancy is allowed. If the timer handler causes the application to process queued messages, any pending queue state flag may be cleared and the message posted again, which may cause the timer to fire before the handler finishes executing.
Does TTimer use an internal/separate thread (via SetTimer)?
No. A utility window is created in the main thread which will receive the timer messages. Upon receiving a timer message this window calls the event handler if one is assigned.
How come that the form that holds the timer (and its OnTimer even)
can still do stuff if a modal MessageDlg is "blocking" the form?
The modal loop continues processing the queue, it calls HandleMessage of the Application in a loop which calls ProcessMessage. Hence timer messages are still processed.
That is a potential cause for re-entrancy mentioned above. You may use a flag or disable/enable the timer to prevent that. Or factor out any message processing in the handler altogether.
The documentations says that SetTimer requires Win2000 minimum. How was TTimer implemented in Win98
Same. Documentation keeps changing, occasionally MSDN drops unsupported OS versions from minimum requirements - rather inconsistently. My XE2 API documentation states:
Minimum operating systems Windows 95, Windows NT 3.1
for the WM_TIMER message.
WM_TIMER messages are never placed in the message queue. They are generated when the queue is empty and a flag indicating that the timer has expired is set. So there can never be more than one WM_TIMER message at a time in the queue and if you application is too busy to process the queue you don't get lots of WM_TIMER messages waiting to be processed.
WM_PAINT messages work the same way.
Related
As I understand it, WM_PAINT messages are not generated when a function like InvalidateRect is called; rather an object that can be be thought of as a flag containing some info about the dirty region is set, and when the other messages in the queue are handled, a single WM_PAINT message is generated which combines the regions from all flags since the last successful WM_PAINT message. Presumably this is done once per HWND associated with a particular thread
I'm wondering how WM_TIMER messages are accumulated? I thought perhaps only the most recent flag for each thread would be kept, but what if different TIMERPROCs and window handles have different timers. What if two SetTimer calls with different intervals point to the same window handle; will one WM_TIMER be generated for each timer ID?
What if two SetTimer calls with different intervals point to the same window handle; will one WM_TIMER be generated for each timer ID?
Yes, there will be one message generated for each distinct timer.
You explicitly state "with different intervals". But this is not a factor. What matters is timer identity, defined by the timer ID. You can have multiple distinct timers with the same interval.
What can happen is that timer events can coalesce if the message queue is not serviced as frequently as the events are logically generated. So if multiple timer intervals elapse between calls to pump the message, only a single timer message is generated. Don't think of timer events as indicating how much timer has elapsed, rather treat them as indicating that at least the specified interval has elapsed.
There are few ways I can put a message for GUI thread.
PostMessage: according to docs, these messages are processed first (before most other messages). If I use this too often, the GUI thread may get stuck in processing only my messages and nothing else (will not respond to keyboard\mouse etc). This is too high-priority method.
SetTimer: WM_TIMER messages are processed last after everything else, so if there is any painting happening (like if I move a window continuously) all time will be spend for processing common messages and WM_TIMER will trigger too late.
This is too low-priority method.
I need something in-between to have my custom message processed ASAP but still leave room for the rest of messages to keep the GUI responsive.
What I'd like to try is to put some message to be processed just in same order as normal messages.
So here is the question, how can I do that?
Added:
I have one thread that prepares video frames and it needs to notify main (UI) thread that a new frame is ready and maybe display it. In a typical game loop it would be something like
process messages until queue is empty
process 1 frame
repeat
But now I can't control message loop because it may be in modal popup or menu.
Assume the answer is "no" (no other way to insert message).
However, in processing posted message I can monitor time passed and immediately signal the same message through WM_TIMER instead of processing it.
update
After some observation it seems no given time (1 ms? 5 ms?) guarantees that input will be processed. What works instead is explicitly checking message queue for input messages:
case MY_MSG:
{
MSG msg;
if(PeekMessage(&msg,0,0,0,PM_NOREMOVE|PM_QS_INPUT))
SetTimer(hwnd,MY_TIMER,0,0);
else
DoWork();
}
return 0;
According to here, GetMessage() is a blocking call which won't return until there's a message can be retrieved from the message queue.
So, how is this blocking behavior implemented?
Does GetMessage() use some kind of spin lock so that the UI thread just busy waits for new messages showing up in the message queue? If so, I guess at least one of my CPU cores should have high usage when a UI application is running. But I didn't see that happen. So how does it work?
ADD 1
Thanks for the hint in the comments. Spin lock is meant to reduce the cost of thread context switch. It shouldn't be used here. I also thought about maybe some event paradigm is used here. But if it is event-driven, how does this event model work?
My guess is like this:
An event for input checking is raised periodically. Perhaps via some hardware timer interrupt. Then the timer interrupt handler will check for various input device buffers for input events. And then put that into certain application's message queue based on the current desktop context, such as which is the active window.
And I guess maybe some other things are also based on the timer interrupt, such as thread context switching.
ADD 2
Based on replies so far. There's some event object that the UI thread waits on. But since UI thread is waiting on something, it is not active and can do nothing by itself yet. And the event object is just some passive state information. So there has to be someone else to wake up the thread upon the event state change. I tink it should be the thread scheduler. And the thread scheduler may be pulsed by the timer interrupt.
The thread scheduler will check the event state periodically and wake up thread and put messages into its queue as necessary.
Am I right about the whole picture?
ADD 3
And there's a remaining question: who modify the state of an event object? Based on here, it seems events are just some data structures that can be modified by any active parties. I think thread scheduler just use the relations among threads and events to decide which thread to run or not.
And by the time a thread is scheduled to run, all it's requirements should already been fulfilled. Such as a message should have been put into its queue before the event it waits on is raised. This is reasonable because otherwise it may be too late. (thanks to RbMm's comments.)
ADD 4
In JDK, the LinkedBlockingDeque type also offers a similar blocking behavior with the take() method.
Retrieves and removes the head of the queue represented by this deque
(in other words, the first element of this deque), waiting if
necessary until an element becomes available.
And the .NET counterpart is the BlockingCollection< T > type. A thread to discuss it.
Here is a thread about how to implement a blocking queue in C#.
The exact implementation is internal and not documented.
Most of the window manager in Windows is implemented in kernel mode. GetMessage is no different. It waits on an event object in kernel mode. When a thread is waiting on an event (or any other kernel-based synchronization object), it does not use any CPU time, because it is not scheduled to run until the wait is satisfied.
When a message is posted to the waiting thread's message queue, or another thread sends a message to a window belonging to the waiting thread, or a timer in the waiting thread fires, or a window in the waiting thread is ready to be painted, the event is signaled, the thread wakes up, and GetMessage() acts accordingly, whether that is to return a posted message to the caller, or to dispatch a sent message directly to the target window procedure and then go back to waiting on the event.
You can see the implementation leaking into the public API if you compare the maximum number of objects you can wait on in WaitForMultipleObjects and MsgWaitForMultipleObjects:
The maximum number of object handles is MAXIMUM_WAIT_OBJECTS.
vs
The maximum number of object handles is MAXIMUM_WAIT_OBJECTS minus
one.
I read some stuff on Win32 and how the message loop works, and there's something that is still unclear to me: What exactly is stored in the message queue? The integer value that corresponds to a message (WM_COMMAND, WM_CREATE, etc) or a pointer to a MSG structure containing the message integer value and other stuff like wParam, lParam, etc?
To answer your question narrowly, each message in the queue stores, at the least,
a window handle to which the message is directed,
the message code, wParam and lParam, as you already correctly noted,
the time when the message was posted, that you retrieve with GetMessageTime(),
for UI messages, the position of the cursor when the message was posted (see GetMessagePos()).
Note that not all messages are actually stored in the queue. Messages that are sent with SendMessage() to a window from the thread that owns the window are never stored; instead, a receiver window's message function is called directly. Messages sent from other threads are stored until processed, and the sending thread blocks until the message is replied to, either by exiting the window function or explicitly with a call to ReplyMessage(). The API function InSendMessage() helps figure out whether the windows function is processing a message sent from another thread.
Messages that you or the system post are stored in the queue, with some exceptions.
WM_TIMER messages are never actually stored; instead, GetMessage() constructs a timer message if there are no other messages in the queue and a timer has matured. This means that, first, the timer messages have the lowest dequeuing priority, and, second, that multiple messages from a short period timer would never overflow queue, even if GetMessage() is not called for a while. As a result, a single WM_TIMER message is sent for the given timer, even if the timer has elapsed multiple times since the last WM_TIMER message from that timer has been processed.
Similarly, WM_QUIT is also not stored, and rather only flagged. GetMessage() pretends to have retrieved the WM_QUIT after the queue has been exhausted, and this is the last message it retrieves.
Another example is the WM_PAINT message (hat tip to #cody-gray for reminding about this). This message is also simulated when any part of the window¹ is marked as "dirty" and needs repainting. This is also a low-priority message, made so that multiple invalidated regions in a window are repainted all at once when the queue becomes empty, to reduce responsiveness of the GUI and reduce flicker. You can force an immediate repaint by calling UpdateWindow(). This function acts like SendMessage(), in the sense that it does not return until the exposed part of the window is redrawn. This function does not send a WM_PAINT to the window if the invalid region of that window is empty, as an obvious optimization.
Probably, there are other exceptions and internal optimizations.
Messages posted with PostMessage() end up in the queue of a thread that owns the window to which the message is posted.
In what form the messages are stored internally, we do not know, and we do not care. Windows API abstracts that completely. The MSG structure is filled in memory you pass to GetMessage() or PeekMessage(). You do not need to know or to worry about the details of internal implementation beyond those documented in Windows SDK guides.
¹ I do not know how exactly WM_PAINT and WM_TIMER are prioritized relative to each other. I assume WM_PAINT has a lower priority, but I may be wrong.
The message queue in Windows is an abstraction. Very helpful to think of it as a queue but the actual implementation of it is far more detailed. There are four distinct sources of messages in Windows:
Messages that are delivered by SendMessage(). Windows directly calls the window procedure, the message isn't returned by Peek/GetMessage() but does require a call to that function to get dispatched. By far the most messages are delivered this way. WM_COMMAND is like that, it is directly sent by the code that translates a key-down event, like TranslateAccelerator(). No queue-like behavior.
Messages that are synthesized from the window state. Best examples are WM_PAINT, delivered when the "window has a dirty rectangle" state flag is set. And WM_TIMER, delivered when the "timer has expired" state flag is set. These are 'low priority' messages, only delivered when the message queue is empty. They are delivered by GetMessage() but do not otherwise live on the queue.
Input event messages for the keyboard and mouse. These are the messages that truly have queue-like behavior. For the keyboard this ensures that type-ahead works, no keystroke gets lost when the program isn't ready to accept a keystroke. A bunch of state is associated with it, the entire state of the keyboard gets copied for example. Roughly the same for the mouse except that there's less state. The WM_MOUSEMOVE message is an interesting corner case, the queue does not store every single pixel traversed by the cursor. Position changes are accumulated into a single message, stored or delivered when necessary.
Messages stored in the queue by an explicit PostMessage() call. That's entirely up to the program code, clearly it only needs to store the arguments of the call plus the time the call was made so it can accurately be replayed back at GetMessage() time.
MSDN has a nice article here explaining everything on messages and message queues.
But to answer your question, the Queue exists for each window, it temporarily stores the messages and their associate parameters, whether of not its a queue of MSG's is implementation defined, but it most likely is (or something similar). It should also be noted that not all messages will go to the queue, some require immediate processing.
When we send a message, "if the specified window was created by the calling thread, the window procedure is called immediately as a subroutine".
But "if the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code." (taken from MSDN documentation for SendMessage).
Now, I don't understand how (or, more appropriately, when) the target windows procedure is called. Of course the target thread will not be preempted (the program counter is not changed). I presume that the call will happen during some wait function (like GetMessage or PeekMessage), it is true? That process is documented in detail somewhere?
Update: the rationale behind it is explained by the QS_SENDMESSAGE flag of GetQueueStatus() and MsgWaitForMultipleObjects():
QS_SENDMESSAGE
A message sent by another thread or application is in the queue.
This, along with additional remarks in MSDN documentation, means that a message sent by another thread is actually posted to the queue. Then, as soon as GetMessage or PeekMessage are called, it will be processed before any other posted message by being sent directly to the window procedure.
I see some confusion here.
According to the MSDN docs, when you touch the message queue of the current thread with the intent of message processing (e.g. if you call PeekMessage or GetMessage), all pending sent (i.e. non-queued) messages from other threads are handled - passed to the WndProc - and then the message queue is checked, so:
sent messages never go through DispatchMessage and are handled as soon as possible:
in the current thread, they are simply passed to WndProc
in another thread, they are handled before any posted message processing
to be able to handle sent messages, the target thread still needs a message pump
PostThreadMessage does just what it states - posts a message in a threads queue - such messages are not directed to any window and must be handled explixitly
the only messages handled by DispatchMessage are those created by PostMessage or some system facility (timers, events, user input, etc.)
to avoid deadlocks, use SendNotifyMessage, SendMessageTimeout or SendMessageCallback instead of plain SendMessage between different threads
For further reference, study the Remarks section of the MSDN PeekMessage entry.
Short answer: When the target thread calls GetMessage (or PeekMessage) followed by DispatchMessage, then the SendMessage from the other thread is received and handled.
I am not certain if the received SendMessage preempts other messages in the queue or not. Either way, a SendMessage from one thread to another is like saying: "Post this message to the other thread's message queue. Return when that thread has finished processing it".
An now for an answer you didn't ask for:
In general, when I program interactions between the main UI thread and a worker thread, I try to avoid using SendMessage. If you aren't careful, you can get into a situation where both threads are deadlocked on each other. (Think of the case where the main thread is calling WaitForSingleObject to wait for the worker thread to complete, but the worker thread is blocked on SendMessage back to the UI thread).
Every windows is associated with a thread. You can use GetWindowThreadProcessId to retrieves the thread of every window. If you send a message to a windows from the other thread with respect of PostThreadMessage the message will be placed in the thread's message queue. The thread must have a get-message loop (with GetMessage for example) to get the messages and dispatch there to the window procedure of the window.
It you call SendMessage instead of PostThreadMessage you call the Windows Procedure directly without placing it in the message queue. Some nonqueued messages are sent also immediately to the destination window procedure, bypassing the system message queue and thread message queue. (see http://msdn.microsoft.com/en-us/library/ms644927(VS.85).aspx#nonqueued_messages). The main reason to use SendMessage instead of PostThreadMessage if you want to give some information from another windows (control) like read a text from an another control during processing of another message. You should do this only if it really needed. So if you use SendMessage to send a message to a windows from another thread your current thread must be blocked for some time.
It can be a good idea to use PostThreadMessage or SendMessageCallback instead of SendMessage if it is possible.