babylon.engine.runner
Async simulation runner for non-blocking UI integration.
This module provides AsyncSimulationRunner, which decouples the UI from the simulation engine by running simulation steps in a background thread and pushing WorldState snapshots to an async queue.
The runner enables: - Non-blocking UI updates during simulation steps - Continuous play mode without freezing the GUI - Queue-based state consumption for flexible UI update strategies
- Usage Example:
>>> from babylon.engine.runner import AsyncSimulationRunner >>> from babylon.engine.simulation import Simulation >>> >>> runner = AsyncSimulationRunner(simulation, tick_interval=1.0) >>> await runner.start() # Begin continuous simulation >>> >>> # UI can poll for states without blocking >>> state = await runner.get_state() >>> if state: ... update_ui(state) >>> >>> await runner.stop()
See also
ai-docs/asyncio-patterns.yamlfor async best practicessrc/babylon/ui/main.pyfor UI integration patterns
Classes
|
Async runner that decouples UI from simulation engine. |
- class babylon.engine.runner.AsyncSimulationRunner(simulation, tick_interval=1.0)[source]
Bases:
objectAsync runner that decouples UI from simulation engine.
The runner wraps a Simulation instance and provides:
Non-blocking steps: Uses
asyncio.to_thread()to runsimulation.step()without blocking the event loop.State queue: Pushes WorldState snapshots to an async queue for the UI to consume at its own pace.
Continuous play:
start()/stop()manage a background loop that steps the simulation at configurable intervals.Queue overflow handling: Drops oldest states when queue is full (MAX_QUEUE_SIZE=10) to prevent memory issues.
- Parameters:
simulation (Simulation)
tick_interval (float)
- MAX_QUEUE_SIZE
Maximum states to buffer before dropping oldest.
Example
>>> runner = AsyncSimulationRunner(sim, tick_interval=0.5) >>> state = await runner.step_once() # Single step >>> print(f"Now at tick {state.tick}")
- Thread Safety:
The runner uses an asyncio.Lock to serialize step_once() calls, ensuring simulation state consistency even with concurrent access.
- __init__(simulation, tick_interval=1.0)[source]
Initialize the async runner with a simulation.
- Parameters:
simulation (
Simulation) – The Simulation facade to run.tick_interval (
float) – Seconds between steps in continuous mode. Must be positive.
- Raises:
ValueError – If tick_interval is not positive.
- Return type:
None
- property simulation: Simulation
Return the wrapped Simulation instance.
- property queue: Queue[WorldState]
Return the state queue for direct access.
- Returns:
The asyncio.Queue containing WorldState snapshots.
- async start()[source]
Start continuous simulation mode.
Creates a background task that steps the simulation at
tick_intervalintervals. Idempotent - calling start() when already running is a no-op.The task reference is stored to prevent garbage collection.
- Return type:
- async stop()[source]
Stop continuous simulation mode.
Cancels the background task and waits for it to finish. Idempotent - calling stop() when not running is a no-op.
- Return type:
- async step_once()[source]
Execute a single simulation step without blocking.
Uses
asyncio.to_thread()to runsimulation.step()in a thread pool, keeping the event loop responsive.The new state is pushed to the queue. If the queue is full, the oldest state is dropped to make room.
- Return type:
- Returns:
The new WorldState after the step.
Note
Uses an asyncio.Lock to serialize concurrent calls, ensuring simulation state consistency.
- async get_state()[source]
Get a state from the queue without blocking.
- Return type:
- Returns:
The next WorldState if available, None otherwise.
- async get_state_blocking(timeout=None)[source]
Get a state from the queue, waiting if necessary.
- Parameters:
timeout (
float|None) – Maximum seconds to wait. None means wait forever.- Return type:
- Returns:
The next WorldState from the queue.
- Raises:
asyncio.TimeoutError – If timeout expires before a state is available.
- async drain_queue()[source]
Remove and return all states from the queue.
- Return type:
- Returns:
List of all WorldState objects that were in the queue, in order from oldest to newest. Empty list if queue was empty.
- async reset(new_simulation)[source]
Reset the runner with a new simulation.
Stops the runner if running, drains the queue, and assigns the new simulation for future steps.
- Parameters:
new_simulation (
Simulation) – The new Simulation instance to use.- Return type: