Async and cancellable variant of WaitForSingleObject. Windows only. Args: handle: A Win32 handle, as a Python integer. Raises: OSError: If the handle is invalid, e.g. when it is already closed.
(obj: int | CData)
| 16 | |
| 17 | |
| 18 | async def WaitForSingleObject(obj: int | CData) -> None: |
| 19 | """Async and cancellable variant of WaitForSingleObject. Windows only. |
| 20 | |
| 21 | Args: |
| 22 | handle: A Win32 handle, as a Python integer. |
| 23 | |
| 24 | Raises: |
| 25 | OSError: If the handle is invalid, e.g. when it is already closed. |
| 26 | |
| 27 | """ |
| 28 | # Allow ints or whatever we can convert to a win handle |
| 29 | handle = _handle(obj) |
| 30 | |
| 31 | # Quick check; we might not even need to spawn a thread. The zero |
| 32 | # means a zero timeout; this call never blocks. We also exit here |
| 33 | # if the handle is already closed for some reason. |
| 34 | retcode = kernel32.WaitForSingleObject(handle, 0) |
| 35 | if retcode == ErrorCodes.WAIT_FAILED: |
| 36 | raise_winerror() |
| 37 | elif retcode != ErrorCodes.WAIT_TIMEOUT: |
| 38 | return |
| 39 | |
| 40 | # Wait for a thread that waits for two handles: the handle plus a handle |
| 41 | # that we can use to cancel the thread. |
| 42 | cancel_handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL) |
| 43 | try: |
| 44 | await trio.to_thread.run_sync( |
| 45 | WaitForMultipleObjects_sync, |
| 46 | handle, |
| 47 | cancel_handle, |
| 48 | abandon_on_cancel=True, |
| 49 | limiter=trio.CapacityLimiter(math.inf), |
| 50 | ) |
| 51 | finally: |
| 52 | # Clean up our cancel handle. In case we get here because this task was |
| 53 | # cancelled, we also want to set the cancel_handle to stop the thread. |
| 54 | kernel32.SetEvent(cancel_handle) |
| 55 | kernel32.CloseHandle(cancel_handle) |
| 56 | |
| 57 | |
| 58 | def WaitForMultipleObjects_sync(*handles: int | CData) -> None: |
searching dependent graphs…