A customer had a custom message loop that was built out of MsgÂWaitÂForÂMultipleÂObjects. Occasionally, they needed to change the list of handles that the message loop was waiting for. How do you add or remove a handle from an active MsgÂWaitÂForÂMultipleÂObjects?
You can’t.
Even if you could, it meant that the return value of MsgÂWaitÂForÂMultipleÂObjects would not be useful. Suppose it returns to say “Handle number 2 was signaled.” You don’t know whether handle 2 was signaled before the handle list was updated, or whether it was signaled after. You don’t know whether it’s referring to the handle number 2 or the new one.
So maybe it’s not a bad thing that you can’t change the list of handles in an active MsgÂWaitÂForÂMultipleÂObjects, since the result wouldn’t be useful. But you can ask the thread to stop waiting, update its handle list, and then go back to waiting.
Since the thread is in a MsgÂWaitÂForÂMultipleÂObjects, it will wake if you send a message to a window that belongs to the thread. You can have a “handle management window” to receive these messages, say
#define WM_ADDHANDLE (WM_USER+0) // wParam = index, lParam = handle #define WM_REMOVEHANDLE (WM_USER+1) // wParam = index
The background thread could send one of these messages if it wanted to add or remove a handle, and the message procedure would perform the corresponding operation.
In reality, you probably need more information than just the handle; you also need to know what to do if that handle is signaled. The lParam is more likely to be a pointer to a structure containing the handle as well as instructions on what the handle means. Those instructions could take the form of a callback function, or it could just be a value from an enum. Pick the design that works for you.
Next time, we’ll look at the case where you don’t want to block the background thread, or if the waiting thread is waiting in WaitÂForÂMultipleÂObjects so the message option is not available.
The simplest idea is to add a dedicated event object to the list of `WaitForMultipleObjects` that serves as a notifier of handle addition/removal. When a handle needs to be added/removed, place the handle to add/remove in a synchronized queue (in case there are many updates) and signal the event. The waiting thread wakes up, sees it's the handle add/removal event, drains the change queue, resets the event, releases the queue, then goes back to waiting.
The above assumes bWaitAll or its equivalent is false. In case it's wait-all, addition is simple --- after waking up, wait again on any added handles....