Skip to content

redsun.aio

Design rationale: ADR 0005.

Running and cancelling coroutines

Shared background event loop, and dispatch of coroutines connected to signals.

redsun runs one background asyncio event loop per process. Device I/O and coroutines connected to psygnal signals run there, off the emitting GUI thread.

run_coro and cancel_task are for general use. Synchronous code, such as a presenter method or a Qt slot, runs a coroutine on the loop with run_coro and gets the result; cancel_task stops a task from whichever thread holds it. The rest of the module is set up by the container at startup and torn down at shutdown. Components must not build their own loop or install a backend.

run_coro

run_coro(
    awaitable: Awaitable[R],
    return_future: Literal[False] = False,
    *,
    timeout: float | None = None,
) -> R
run_coro(
    awaitable: Awaitable[R], return_future: Literal[True]
) -> Future[R]
run_coro(
    awaitable: Awaitable[R],
    return_future: bool = False,
    *,
    timeout: float | None = None,
) -> R | Future[R]

Run awaitable on the shared loop and return its result.

With return_future, return the Future at once instead of waiting; that is safe from any thread, the shared loop's own included. A wait that ends without a result, on timeout or when the waiting thread is interrupted, cancels awaitable.

Parameters:

Name Type Description Default
timeout float | None

Seconds to wait; None waits until it completes.

None

Raises:

Type Description
RuntimeError

If called on the shared loop's thread without return_future, where waiting would block the loop that has to run awaitable.

TimeoutError

If timeout passes first.

cancel_task

cancel_task(task: Future[R]) -> None

Cancel task from any thread.

The cancellation is handed to the task's loop and reaches the task the next time it waits, or not at all if it has finished by then.