Funkymunky said:
PeekMessage, which blocks until a message is received
Who told you about?
PeekMessage from MSDN
Dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist)
doesn't say anything about blocking the thread until a message receives, this is the purpose of the game loop to run until some important OS messages arrive. The issue is that you have to capture those messages to handle something like input, window resize and application exit events send from the OS to your process. If you ignore those messages then there will be a message stall and Windows will detect your application to hang (while displaying the message box to the user) so you want to prevent this.
But you are free to change this behavior as long as you are publishing OS messages to your engine! Modern game engines are multithreaded (at least the AAA ones) and split up the game loop in several ways. However, code may need to optain the exact frametime so you need to track that in your message thread because the message handling is part of the delay between two frames.
One possible path is that the engine will start to prepare the update loop in another thread while render whatever objects is to display when there is space to do so. It then awaits while still processing messages until the update thread is finished and start rendering again. You can use events, a render queue or any other appropirate method to update your game state while also receiving input events from the render thread (where your message pump lives), for example user input that has to be propagated to the update thread. You still should handle rendering (or at least display logic) in your main thread or else there could occure ugly artifacts while Windows is doing something with it's own renderer that handles the GDI drawing for example.
Multithreading is difficult and even experts (that I don't count myself to) are struggling when it comes to designing a multithreaded architecture so it is easier for most games/ game engines to have a single threaded game loop. Unity is such an example, even while they are moving more and more into threaded environment, user code is still and has to be executed single threaded in the main thread