I'm implementing a Win32 Console text editor that has an internal message queue for passing around information about which areas to redraw, messages to/from plugins, etc. I prefer it to be single-threaded by default (if there's nothing happening that requires additional threads). I'm considering 2 message queue implementation strategies:
WaitForMultipleObjectsEx
to wait for internal messages and user input simultaneously, passing both console input handle and Event handle. In this case, text editor can live entirely within a single thread.GetQueuedCompletionStatus
to get messages, and another reading user input and sending it to queue via PostQueuedCompletionStatus
. The reason it that console input handle cannot be overlapped and WaitFor*
functions don't accept Completion Port as a waitable handle, so it's not possible to wait on them simultaneously. Just like in the first setup, both threads don't waste CPU time when there's no input or events, but each keypress has to be passed from one thread to another via IOCP.Which design is overall better?
Is performance and latency drawback from passing each keypress via IOCP significant for a text editor?
Performance and latency of IOCP is fine for your purpose. I wouldn’t however translate each key press into PostQueuedCompletionStatus. I’d rather PostQueuedCompletionStatus to enqueue multiple keypresses at once, whatever count you get from ReadConsoleInput.
I think performance difference is minimal, either one can be faster depending on the environment. And WaitForMultipleObjects is much easier to implement.
P.S. You sure you need message queue at all? Why don’t you process these redraw requests / plugin messages in whichever thread fired those, using e.g. critical section to guard (console output + your shared state)? If your congestion is low, like 100Hz messages + 15Hz keypresses, and you’ll process them fast, this will get you even lower latency than IOCP or any other queues: with low congestion or brief locking, critical sections don’t even switch to kernel for lock/unlock. This will also simplify design, your main thread will sleep on blocking ReadConsoleInput() call, no need to WaitFor.. before that.