bool WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort, DWORD timeout /*must not be INFINITE*/) { PFC_ASSERT( timeout != INFINITE ); const DWORD entry = GetTickCount(); const HANDLE handles[2] = {ev, abort.get_abort_event()}; for(;;) { const DWORD done = GetTickCount() - entry; if (done >= timeout) return false; SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(2, handles, FALSE, timeout - done, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: return false; case WAIT_OBJECT_0: return true; case WAIT_OBJECT_0 + 1: throw exception_aborted(); case WAIT_OBJECT_0 + 2: ProcessPendingMessages(); break; case WAIT_FAILED: WIN32_OP_FAIL(); default: uBugCheck(); } } }
void writeOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, const void * in,DWORD inBytes, abort_callback & abort) { abort.check(); if (inBytes == 0) return; OVERLAPPED ol = {}; fillOverlapped(ol, myEvent, position); ResetEvent(myEvent); DWORD bytesWritten; SetLastError(NO_ERROR); if (WriteFile( handle, in, inBytes, &bytesWritten, &ol)) { // succeeded already? if (bytesWritten != inBytes) throw exception_io(); return; } { const DWORD code = GetLastError(); if (code != ERROR_IO_PENDING) exception_io_from_win32(code); } const HANDLE handles[] = {myEvent, abort.get_abort_event()}; SetLastError(NO_ERROR); DWORD state = WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE); if (state == WAIT_OBJECT_0) { try { WIN32_IO_OP( GetOverlappedResult(handle,&ol,&bytesWritten,TRUE) ); } catch(...) { CancelIo(handle); throw; } if (bytesWritten != inBytes) throw exception_io(); return; } CancelIo(handle); throw exception_aborted(); }
t_size MultiWaitAbortable_MsgLoop(const HANDLE * ev, t_size evCount, abort_callback & abort) { pfc::array_t<HANDLE> handles; handles.set_size(evCount + 1); handles[0] = abort.get_abort_event(); pfc::memcpy_t(handles.get_ptr() + 1, ev, evCount); for(;;) { SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(handles.get_count(), handles.get_ptr(), FALSE, INFINITE, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: PFC_ASSERT(!"How did we get here?"); uBugCheck(); case WAIT_OBJECT_0: throw exception_aborted(); case WAIT_FAILED: WIN32_OP_FAIL(); default: { t_size index = (t_size)(status - (WAIT_OBJECT_0 + 1)); if (index == evCount) { ProcessPendingMessages(); } else if (index < evCount) { return index; } else { uBugCheck(); } } } } }
mutexScope::mutexScope(HANDLE hMutex_, abort_callback & abort) : hMutex(hMutex_) { HANDLE h[2] = {hMutex, abort.get_abort_event()}; switch( WaitForMultipleObjects(2, h, FALSE, INFINITE) ) { case WAIT_OBJECT_0: break; // and enter case WAIT_OBJECT_0+1: throw exception_aborted(); default: uBugCheck(); } }
void CMutex::AcquireByHandle( HANDLE hMutex, abort_callback & aborter ) { SetLastError(0); HANDLE hWait[2] = {hMutex, aborter.get_abort_event()}; switch(WaitForMultipleObjects( 2, hWait, FALSE, INFINITE ) ) { case WAIT_FAILED: WIN32_OP_FAIL_CRITICAL("WaitForSingleObject"); case WAIT_OBJECT_0: return; case WAIT_OBJECT_0 + 1: PFC_ASSERT( aborter.is_aborting() ); throw exception_aborted(); default: uBugCheck(); } }
HANDLE createFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, abort_callback & abort) { abort.check(); return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); // CancelSynchronousIo() doesn't f*****g work. Useless. #if 0 pCancelSynchronousIo_t pCancelSynchronousIo = (pCancelSynchronousIo_t) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CancelSynchronousIo"); if (pCancelSynchronousIo == NULL) { #ifdef _DEBUG uDebugLog() << "Async CreateFile unavailable - using regular"; #endif return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } else { #ifdef _DEBUG uDebugLog() << "Starting async CreateFile..."; pfc::hires_timer t; t.start(); #endif createFileData_t data = {lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, NULL, 0}; HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, createFileProc, &data, 0, NULL); HANDLE waitHandles[2] = {hThread, abort.get_abort_event()}; switch(WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE)) { case WAIT_OBJECT_0: // succeeded break; case WAIT_OBJECT_0 + 1: // abort #ifdef _DEBUG uDebugLog() << "Aborting async CreateFile..."; #endif pCancelSynchronousIo(hThread); WaitForSingleObject(hThread, INFINITE); break; default: uBugCheck(); } CloseHandle(hThread); SetLastError(data.dwErrorCode); #ifdef _DEBUG uDebugLog() << "Async CreateFile completed in " << pfc::format_time_ex(t.query(), 6) << ", status: " << (uint32_t) data.dwErrorCode; #endif if (abort.is_aborting()) { if (data.hResult != INVALID_HANDLE_VALUE) CloseHandle(data.hResult); throw exception_aborted(); } return data.hResult; } #endif }
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(); } }
DWORD readOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, void * out, DWORD outBytes, abort_callback & abort) { abort.check(); if (outBytes == 0) return 0; OVERLAPPED ol = {}; fillOverlapped(ol, myEvent, position); ResetEvent(myEvent); DWORD bytesDone; SetLastError(NO_ERROR); if (ReadFile( handle, out, outBytes, &bytesDone, &ol)) { // succeeded already? return bytesDone; } { const DWORD code = GetLastError(); switch(code) { case ERROR_HANDLE_EOF: case ERROR_BROKEN_PIPE: return 0; case ERROR_IO_PENDING: break; // continue default: exception_io_from_win32(code); }; } const HANDLE handles[] = {myEvent, abort.get_abort_event()}; SetLastError(NO_ERROR); DWORD state = WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE); if (state == WAIT_OBJECT_0) { SetLastError(NO_ERROR); if (!GetOverlappedResult(handle,&ol,&bytesDone,TRUE)) { const DWORD code = GetLastError(); if (code == ERROR_HANDLE_EOF || code == ERROR_BROKEN_PIPE) bytesDone = 0; else { CancelIo(handle); exception_io_from_win32(code); } } return bytesDone; } CancelIo(handle); throw exception_aborted(); }
void SleepAbortable_MsgLoop(abort_callback & abort, DWORD timeout /*must not be INFINITE*/) { PFC_ASSERT( timeout != INFINITE ); const DWORD entry = GetTickCount(); const HANDLE handles[1] = {abort.get_abort_event()}; for(;;) { const DWORD done = GetTickCount() - entry; if (done >= timeout) return; SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(1, handles, FALSE, timeout - done, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: return; case WAIT_OBJECT_0: throw exception_aborted(); case WAIT_OBJECT_0 + 1: ProcessPendingMessages(); default: throw exception_win32(GetLastError()); } } }
void WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort) { const HANDLE handles[2] = {ev, abort.get_abort_event()}; for(;;) { SetLastError(0); const DWORD status = MsgWaitForMultipleObjects(2, handles, FALSE, INFINITE, QS_ALLINPUT); switch(status) { case WAIT_TIMEOUT: PFC_ASSERT(!"How did we get here?"); uBugCheck(); case WAIT_OBJECT_0: return; case WAIT_OBJECT_0 + 1: throw exception_aborted(); case WAIT_OBJECT_0 + 2: ProcessPendingMessages(); break; case WAIT_FAILED: WIN32_OP_FAIL(); default: uBugCheck(); } } }