second commit
This commit is contained in:
62
venv/Lib/site-packages/trio/_wait_for_object.py
Normal file
62
venv/Lib/site-packages/trio/_wait_for_object.py
Normal file
@@ -0,0 +1,62 @@
|
||||
import math
|
||||
from . import _timeouts
|
||||
import trio
|
||||
from ._core._windows_cffi import (
|
||||
ffi,
|
||||
kernel32,
|
||||
ErrorCodes,
|
||||
raise_winerror,
|
||||
_handle,
|
||||
)
|
||||
|
||||
|
||||
async def WaitForSingleObject(obj):
|
||||
"""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.
|
||||
|
||||
"""
|
||||
# Allow ints or whatever we can convert to a win handle
|
||||
handle = _handle(obj)
|
||||
|
||||
# Quick check; we might not even need to spawn a thread. The zero
|
||||
# means a zero timeout; this call never blocks. We also exit here
|
||||
# if the handle is already closed for some reason.
|
||||
retcode = kernel32.WaitForSingleObject(handle, 0)
|
||||
if retcode == ErrorCodes.WAIT_FAILED:
|
||||
raise_winerror()
|
||||
elif retcode != ErrorCodes.WAIT_TIMEOUT:
|
||||
return
|
||||
|
||||
# Wait for a thread that waits for two handles: the handle plus a handle
|
||||
# that we can use to cancel the thread.
|
||||
cancel_handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
||||
try:
|
||||
await trio.to_thread.run_sync(
|
||||
WaitForMultipleObjects_sync,
|
||||
handle,
|
||||
cancel_handle,
|
||||
cancellable=True,
|
||||
limiter=trio.CapacityLimiter(math.inf),
|
||||
)
|
||||
finally:
|
||||
# Clean up our cancel handle. In case we get here because this task was
|
||||
# cancelled, we also want to set the cancel_handle to stop the thread.
|
||||
kernel32.SetEvent(cancel_handle)
|
||||
kernel32.CloseHandle(cancel_handle)
|
||||
|
||||
|
||||
def WaitForMultipleObjects_sync(*handles):
|
||||
"""Wait for any of the given Windows handles to be signaled."""
|
||||
n = len(handles)
|
||||
handle_arr = ffi.new("HANDLE[{}]".format(n))
|
||||
for i in range(n):
|
||||
handle_arr[i] = handles[i]
|
||||
timeout = 0xFFFFFFFF # INFINITE
|
||||
retcode = kernel32.WaitForMultipleObjects(n, handle_arr, False, timeout) # blocking
|
||||
if retcode == ErrorCodes.WAIT_FAILED:
|
||||
raise_winerror()
|
||||
Reference in New Issue
Block a user