Mercurial > repos > blastem
diff util.c @ 2703:829205a9647a default tip
Pump events and allow debug window interaction while paused in CPU debugger on Windows
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 04 Jul 2025 21:24:15 -0700 |
parents | 143cb5762ec9 |
children |
line wrap: on
line diff
--- a/util.c Fri Jul 04 21:23:48 2025 -0700 +++ b/util.c Fri Jul 04 21:24:15 2025 -0700 @@ -757,6 +757,70 @@ return WSAGetLastError() == WSAEWOULDBLOCK; } +typedef struct { + HANDLE request_event; + HANDLE reply_event; + CRITICAL_SECTION lock; + FILE *f; + char *dst; + size_t size; +} stdio_timeout_state; + +static DWORD WINAPI stdio_timeout_thread(LPVOID param) +{ + stdio_timeout_state *state = param; + EnterCriticalSection(&state->lock); + for(;;) + { + while (!state->f) + { + LeaveCriticalSection(&state->lock); + WaitForSingleObject(state->request_event, INFINITE); + EnterCriticalSection(&state->lock); + } + char *dst = state->dst; + size_t size = state->size; + FILE *f = state->f; + LeaveCriticalSection(&state->lock); + dst = fgets(dst, size, f); + EnterCriticalSection(&state->lock); + state->dst = dst; + state->f = NULL; + SetEvent(&state->reply_event); + } + LeaveCriticalSection(&state->lock); + + return 0; +} + +char *fgets_timeout(char *dst, size_t size, FILE *f, uint64_t timeout_usec, void (*timeout_cb)(void)) +{ + static HANDLE workerThread; + static stdio_timeout_state state; + if (!workerThread) { + InitializeCriticalSection(&state.lock); + state.request_event = CreateEventA(NULL, FALSE, FALSE, NULL); + state.reply_event = CreateEventA(NULL, FALSE, FALSE, NULL); + workerThread = CreateThread(NULL, 64 * 1024, stdio_timeout_thread, &state, 0, NULL); + } + EnterCriticalSection(&state.lock); + state.f = f; + state.dst = dst; + state.size = size; + SetEvent(state.request_event); + while (state.f) + { + LeaveCriticalSection(&state.lock); + WaitForSingleObject(state.reply_event, timeout_usec / 1000); + EnterCriticalSection(&state.lock); + if (state.f) { + timeout_cb(); + } + } + LeaveCriticalSection(&state.lock); + return state.dst; +} + #else #include <fcntl.h> #include <signal.h> @@ -864,6 +928,26 @@ } return exe_dir; } + +char *fgets_timeout(char *dst, size_t size, FILE *f, uint64_t timeout_usec, void (*timeout_cb)(void)) +{ + int wait = 1; + fd_set read_fds; + FD_ZERO(&read_fds); + struct timeval timeout; + do { + timeout.tv_sec = timeout_usec / 1000000; + timeout.tv_usec = timeout_usec % 1000000; + FD_SET(fileno(stdin), &read_fds); + if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) >= 1) { + wait = 0; + } else { + timeout_cb(); + } + } while (wait); + return fgets(dst, size, f); +} + #include <dirent.h> #ifdef __ANDROID__