fn wait_thread()

in src/platform_impl/windows/event_loop.rs [298:361]


fn wait_thread(parent_thread_id: DWORD, msg_window_id: HWND) {
    unsafe {
        let mut msg: winuser::MSG;

        let cur_thread_id = processthreadsapi::GetCurrentThreadId();
        winuser::PostThreadMessageW(
            parent_thread_id,
            *SEND_WAIT_THREAD_ID_MSG_ID,
            0,
            cur_thread_id as LPARAM,
        );

        let mut wait_until_opt = None;
        'main: loop {
            // Zeroing out the message ensures that the `WaitUntilInstantBox` doesn't get
            // double-freed if `MsgWaitForMultipleObjectsEx` returns early and there aren't
            // additional messages to process.
            msg = mem::zeroed();

            if wait_until_opt.is_some() {
                if 0 != winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, winuser::PM_REMOVE) {
                    winuser::TranslateMessage(&mut msg);
                    winuser::DispatchMessageW(&mut msg);
                }
            } else {
                if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) {
                    break 'main;
                } else {
                    winuser::TranslateMessage(&mut msg);
                    winuser::DispatchMessageW(&mut msg);
                }
            }

            if msg.message == *WAIT_UNTIL_MSG_ID {
                wait_until_opt = Some(*WaitUntilInstantBox::from_raw(msg.lParam as *mut _));
            } else if msg.message == *CANCEL_WAIT_UNTIL_MSG_ID {
                wait_until_opt = None;
            }

            if let Some(wait_until) = wait_until_opt {
                let now = Instant::now();
                if now < wait_until {
                    // MsgWaitForMultipleObjects tends to overshoot just a little bit. We subtract
                    // 1 millisecond from the requested time and spinlock for the remainder to
                    // compensate for that.
                    let resume_reason = winuser::MsgWaitForMultipleObjectsEx(
                        0,
                        ptr::null(),
                        dur2timeout(wait_until - now).saturating_sub(1),
                        winuser::QS_ALLEVENTS,
                        winuser::MWMO_INPUTAVAILABLE,
                    );
                    if resume_reason == winerror::WAIT_TIMEOUT {
                        winuser::PostMessageW(msg_window_id, *PROCESS_NEW_EVENTS_MSG_ID, 0, 0);
                        wait_until_opt = None;
                    }
                } else {
                    winuser::PostMessageW(msg_window_id, *PROCESS_NEW_EVENTS_MSG_ID, 0, 0);
                    wait_until_opt = None;
                }
            }
        }
    }
}