Futures
Futures in ExEngine represent the outcome of asynchronous operations. They provide a way to handle long-running tasks without blocking the main execution thread. Futures allow you to submit events for execution and then either wait for their completion or continue with other tasks, checking back later for results. This enables efficient, non-blocking execution of complex workflows.
When you submit an event to the ExecutionEngine, it returns a future:
from exengine import ExecutionEngine
from exengine.events import SomeEvent
engine = ExecutionEngine.get_instance()
event = SomeEvent()
future = engine.submit(event)
You can then use this future to interact with the ongoing operation.
Waiting for Completion + Error Handling
To wait for an event to complete and get its result:
result = future.await_execution()
This will block until the event completes.
If an event raises an exception during its execution, you can catch it when awaiting the future:
try:
result = future.await_execution()
except Exception as e:
print(f"Event failed with error: {e}")
Checking Completion Status
You can check if an event has completed without blocking:
if future.is_execution_complete():
print("Event has completed")
else:
print("Event is still running")
Notifications
Futures can be used to await specific notifications from an event:
future.await_notification(SomeSpecificNotification)
This will block until the specified notification is received. If the notification has already been received when this method is called, it will return immediately.
Retrieving Data
For data-producing events, use the future’s await_data method to retrieve data:
# Retrieve a single piece of data
data, metadata = future.await_data({'time': 2}, return_data=True, return_metadata=True)
# Retrieve multiple pieces of data
data_list = future.await_data([{'time': 0}, {'time': 1}, {'time': 2}], return_data=True)
The data_coordinates parameter can specify a single piece of data or multiple pieces.
Stopping Execution
If an event is stoppable (inherits from Stoppable), you can use the future to stop it:
future.stop(await_completion=True)
This requests the event to stop its execution. The await_completion parameter determines whether the method should block until the event has stopped.
Aborting Execution
Similarly, for abortable events (inheriting from Abortable):
future.abort(await_completion=True)
This immediately terminates the event’s execution. As with stop, await_completion determines whether to wait for the abortion to complete.