Mercurial > foo_out_sdl
diff foosdk/sdk/foobar2000/helpers/ThreadUtils.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/helpers/ThreadUtils.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,161 @@ +#include "StdAfx.h" + +#include "ThreadUtils.h" +#include "rethrow.h" + +#include <exception> + +namespace ThreadUtils { + bool CRethrow::exec( std::function<void () > f ) throw() { + m_exception = nullptr; + bool rv = false; + try { + f(); + rv = true; + } catch( ... ) { + m_exception = std::current_exception(); + } + + return rv; + } + + void CRethrow::rethrow() const { + if (m_exception) std::rethrow_exception(m_exception); + } +} +#ifdef _WIN32 + +#include "win32_misc.h" + +#ifdef FOOBAR2000_MOBILE +#include <pfc/pp-winapi.h> +#endif + + +namespace ThreadUtils { + bool WaitAbortable(HANDLE ev, abort_callback & abort, DWORD timeout) { + const HANDLE handles[2] = {ev, abort.get_abort_event()}; + SetLastError(0); + const DWORD status = WaitForMultipleObjects(2, handles, FALSE, timeout); + switch(status) { + case WAIT_TIMEOUT: + PFC_ASSERT( timeout != INFINITE ); + return false; + case WAIT_OBJECT_0: + return true; + case WAIT_OBJECT_0 + 1: + throw exception_aborted(); + case WAIT_FAILED: + WIN32_OP_FAIL(); + default: + uBugCheck(); + } + } +#ifdef FOOBAR2000_DESKTOP_WINDOWS + void ProcessPendingMessagesWithDialog(HWND hDialog) { + MSG msg = {}; + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (!IsDialogMessage(hDialog, &msg)) { + DispatchMessage(&msg); + } + } + } + void ProcessPendingMessages() { + MSG msg = {}; + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + DispatchMessage(&msg); + } + } + void WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort) { + abort.check(); + const HANDLE handles[2] = {ev, abort.get_abort_event()}; + MultiWait_MsgLoop(handles, 2); + abort.check(); + + } + t_size MultiWaitAbortable_MsgLoop2(const HANDLE* ev, t_size evCount, abort_callback& abort) { + abort.check(); + const size_t evCountEx = evCount + 1; + HANDLE handles1[16]; + pfc::array_staticsize_t<HANDLE> handles2; + HANDLE* pHandles = handles1; + if (evCountEx > 16) { + handles2.set_size_discard(evCountEx); + pHandles = handles2.get_ptr(); + } + pHandles[0] = abort.get_abort_event(); + pfc::memcpy_t(pHandles + 1, ev, evCount); + DWORD status = MultiWait_MsgLoop(pHandles, (DWORD) evCountEx); + abort.check(); + size_t ret = (size_t)(status - WAIT_OBJECT_0 - 1); + PFC_ASSERT(ret < evCount); + return ret; + } + + t_size MultiWaitAbortable_MsgLoop(const HANDLE * ev, t_size evCount, abort_callback & abort) { + // Retval is 1-based! + // Originally a bug, now kept for compatibility if someone relies on this + // Use MultiWaitAbortable_MsgLoop2() instead + return MultiWaitAbortable_MsgLoop2(ev, evCount, abort) + 1; + } + + void SleepAbortable_MsgLoop(abort_callback & abort, DWORD timeout) { + HANDLE handles[] = { abort.get_abort_event() }; + MultiWait_MsgLoop(handles, 1, timeout); + abort.check(); + } + + bool WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort, DWORD timeout) { + abort.check(); + HANDLE handles[2] = { abort.get_abort_event(), ev }; + DWORD status = MultiWait_MsgLoop(handles, 2, timeout); + abort.check(); + return status != WAIT_TIMEOUT; + } + + DWORD MultiWait_MsgLoop(const HANDLE* ev, DWORD evCount) { + for (;; ) { + SetLastError(0); + const DWORD status = MsgWaitForMultipleObjects((DWORD) evCount, ev, FALSE, INFINITE, QS_ALLINPUT); + if (status == WAIT_FAILED) WIN32_OP_FAIL(); + if (status == WAIT_OBJECT_0 + evCount) { + ProcessPendingMessages(); + } else if ( status >= WAIT_OBJECT_0 && status < WAIT_OBJECT_0 + evCount ) { + return status; + } else { + uBugCheck(); + } + } + } + + DWORD MultiWait_MsgLoop(const HANDLE* ev, DWORD evCount, DWORD timeout) { + if (timeout == INFINITE) return MultiWait_MsgLoop(ev, evCount); + const DWORD entry = GetTickCount(); + DWORD now = entry; + for (;;) { + const DWORD done = now - entry; + if (done >= timeout) return WAIT_TIMEOUT; + SetLastError(0); + const DWORD status = MsgWaitForMultipleObjects((DWORD)evCount, ev, FALSE, timeout - done, QS_ALLINPUT); + if (status == WAIT_FAILED) WIN32_OP_FAIL(); + if (status == WAIT_OBJECT_0 + evCount) { + ProcessPendingMessages(); + } else if (status == WAIT_TIMEOUT || (status >= WAIT_OBJECT_0 && status < WAIT_OBJECT_0 + evCount) ) { + return status; + } else { + uBugCheck(); + } + now = GetTickCount(); + } + } + + bool pfcWaitMsgLoop(HANDLE ev, double timeout) { + DWORD ms = pfc::event::g_calculate_wait_time(timeout); + DWORD status = MultiWait_MsgLoop(&ev, 1, ms); + return status == WAIT_OBJECT_0; + } + +#endif // FOOBAR2000_DESKTOP_WINDOWS + +} +#endif \ No newline at end of file
