.. _futures: ####### 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python # 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: .. code-block:: python 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``): .. code-block:: python 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.