simvx.core.ai.async_slot¶
AsyncSlot: a non-blocking bridge from the synchronous frame loop to one awaitable.
The engine frame loop is purely synchronous (SceneTree.tick drives generator
coroutines with gen.send(dt)); there is no asyncio event loop on the frame
thread, and a blocking await there would freeze the game. AsyncSlot owns
one daemon thread running one long-lived asyncio loop. The frame thread only ever
calls :meth:submit (returns immediately via run_coroutine_threadsafe) and
- meth:
poll(non-blocking; reads a finished result orNone).
This mirrors two precedents the engine already ships: AssetServer.flush
(snapshot-under-lock then dispatch) and GitStatusProvider (daemon thread +
lock-guarded poll + self-disable-and-log on failure). The slot is LLM-agnostic:
it bridges any awaitable, so the hybrid commander and node-gen capstone reuse it
unchanged.
Policy:
Coalesce: at most one in-flight future. :meth:
submitis a no-op while a call is pending (the dropped coroutine factory is never invoked, so there is no “coroutine was never awaited” warning).Graceful degrade: :meth:
polllogs the specific failure and returnsNoneso the caller keeps its last good value, never a bareexceptthat hides bugs.Teardown: :meth:
closestops the loop and joins the daemon thread; it is idempotent. The thread is a daemon so a crashed game still exits.
Module Contents¶
Classes¶
One daemon asyncio loop bridging a single in-flight awaitable to the frame. |
Data¶
API¶
- simvx.core.ai.async_slot.log¶
‘getLogger(…)’
- class simvx.core.ai.async_slot.AsyncSlot(*, thread_name: str = 'simvx-async-slot')[source]¶
One daemon asyncio loop bridging a single in-flight awaitable to the frame.
Initialization
- property pending: bool[source]¶
True if a submitted call is still running (used by callers to gate cadence).
- submit(factory: simvx.core.ai.async_slot.CoroFactory[simvx.core.ai.async_slot.T]) bool[source]¶
Submit a coroutine factory to the loop, coalescing to one in-flight call.
Returns
Trueif accepted (no call was pending),Falseif dropped because a call is already in flight or the slot is closed. The dropped factory is never invoked, so no coroutine is created and abandoned.
- poll() simvx.core.ai.async_slot.T | None[source]¶
Return a freshly completed result, or
Noneif nothing new / it failed.Non-blocking: never awaits. On success the slot is cleared and the value returned. On exception the failure is logged and
Noneis returned so the caller retains its last good value. While a call is still pending, or nothing has been submitted, returnsNone.