Is this reliable, or have I missed something?
I want a drop-in replacement for WaitForSingleObject (sans the return type, I like HRESULT
much better than any other error codes).
This code works in a plugin DLL for third party closed-source software. I don’t have source code of that app, i.e. if you ask “what else might happen on the same thread while it waits?” the answer is “anything at all”.
constexpr HRESULT E_TIMEOUT = HRESULT_FROM_WIN32( ERROR_TIMEOUT );
constexpr int MSGF_SLEEPMSG = 0x5300;
inline HRESULT getLastHr() { return HRESULT_FROM_WIN32( GetLastError() ); }
// Same as WaitForSingleObject but processes windows messages while it waits.
HRESULT msgWaitForSingleObject( HANDLE h, DWORD ms )
{
// https://blogs.msdn.microsoft.com/oldnewthing/20060126-00/?p=32513/
while( true )
{
const DWORD started = GetTickCount();
const DWORD res = MsgWaitForMultipleObjectsEx( 1, &h, ms, QS_ALLINPUT, MWMO_INPUTAVAILABLE );
if( WAIT_OBJECT_0 == res )
return S_OK;
if( WAIT_OBJECT_0 + 1 == res )
{
MSG msg;
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
PostQuitMessage( (int)msg.wParam );
return S_FALSE; // Abandoned due to WM_QUIT
}
if( !CallMsgFilter( &msg, MSGF_SLEEPMSG ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
const DWORD elapsed = GetTickCount() - started; //< This works OK even when DWORD overflows: https://codereview.stackexchange.com/a/129670/46194
if( elapsed > ms )
return E_TIMEOUT;
ms -= elapsed;
continue;
}
if( WAIT_TIMEOUT == res )
return E_TIMEOUT;
HRESULT hr = getLastHr();
if( FAILED( hr ) )
return hr;
return E_UNEXPECTED; // Unasked IO_COMPLETION or ABANDONED?
}
}
ms -= elapsed
. I myself would make such int parameter const and copy it to non-const variable. The optimization compiler would completely minimize the overhead but it helps in debug mode so that we see the parameter without going up the stack. \$\endgroup\$const
modifier for the parameter. \$\endgroup\$MsgWaitForMultipleObjectsEx
will happily acceptconst
input variable instead of the non-const. \$\endgroup\$