Description
- Proposed
- Prototype: Not Started
- Implementation: Not Started
- Specification: Not Started
Summary
Emulate async/await or observable semantics for long running actions, e.g. moving a motor (see also the observable guide and asynchronous programming patterns).
Motivation
Following up on the concerns raised in #58, we propose here a standard way to handle and report completion / cancellation for asynchronous actions in Harp devices. This is an important problem as many experimental tasks can be long-running such as moving a motor, delivering a finite pulse, running a calibration cycle, state machines, etc.
By having a standard way to reason about asynchronous programming of tasks in Harp devices, we can enable automation, reuse code, make teaching easier, simplify data analysis, etc.
Detailed Design
- Send a command to an "async register"
- A response is sent as soon as the task is created (started)
- This response carries the unique ID for the task (we propose to use the timestamp of the response as the task ID)
- The ID of the register which will report termination must be specified somewhere (could be in the device schema or in the response)
- if the async register is not reentrant, and an async task is already running, an error may be sent (in this case we don't need to track the task ID specifically in firmware because there can be only one; or we can just use a volatile memory somewhere). In case an error is not sent, a device may choose to implement any of the existing reactive semantics:
- Merge (run multiple commands in parallel)
- Concat (run multiple commands sequentially)
- Switch (cancel ongoing command and switch to the new one)
- in this last case a cancelled response to the previous command should be sent, as detailed in Message protocol enhancements for scheduled execution #15
- A separate register signals completion or failure of the async action
- Cancellation may be supported by passing to the "async register" the response command with the cancellation bit proposed in Message protocol enhancements for scheduled execution #15
- if the function does not support cancellation, an error message is sent
- if the function has already been completed or cancelled, the cancellation request is ignored but a response may be sent (the final design from Message protocol enhancements for scheduled execution #15 should be adopted for consistency)
- Scheduled execution of a command to an async register is compatible since scheduled commands only emit a response after they are executed. In this case what we are scheduling is the start of the task. This means we can schedule for example an async command to start in 10 seconds. After the 10 seconds elapse the device will emit a response saying the async action has started. Cancellation is now two-fold: we can choose to cancel the scheduled start of the async task by sending the cancelled scheduled command during the 10 second window, or the task itself after it starts as described above.
- Progress registers are supported (for now they are simple event registers implemented on a by-need basis).
Drawbacks
Generic solutions are potentially complex as they may again require the need to handle dynamic data structures, task queues and scheduling, etc.
However, if solutions are implementation-specific to certain registers it could also be simpler since assumptions about its function can be relied upon.
Alternatives
Related proposals / issues:
- Register WRITE Reply Behavior for Slow Routines #58
- Message protocol enhancements for scheduled execution #15
Impact of not doing this is having proliferation of ad-hoc solutions requiring understanding of asynchronous programming on a device-by-device and register-by-register basis.
Unresolved Questions
To be reviewed.