(io): avoid reentrance in update loops
Description
In our navigation applications based on video and tracked sensors, we synchronise all source data with sight::module::sync::synchronizer
. It is designed to be used in this kind of typical sequence, that we could call an "update loop":
sequenceDiagram
grabber->>synchronizer: object_pushed
synchronizer->>process_service1: synchronization_done
process_service1->>process_service2: updated
process_service2->>synchronizer: synchronize
However, in bigger applications it is easy to mess up and call synchronize() multiple times before the update loop completes. This leads to have "intricated" update loops:
sequenceDiagram
grabber->>synchronizer: object_pushed
logic_service->>synchronizer: synchronize
grabber->>synchronizer: object_pushed
synchronizer->>process_service1: synchronization_done
process_service1->>process_service2: updated
synchronizer->>process_service1: synchronization_done
process_service1->>process_service2: updated
process_service2->>synchronizer: synchronize
process_service2->>synchronizer: synchronize
For the developer, it is very annoying as it is easy to mess up in complex applications.
Functional specifications
We would like somehow, any synchronisation request to be discarded until we complete the update loop.
sequenceDiagram
grabber->>synchronizer: object_pushed
logic_service->>synchronizer: try_sync
grabber->>synchronizer: object_pushed
logic_service->>synchronizer: try_sync
synchronizer->>process_service1: synchronization_done
process_service1->>process_service2: updated
process_service2->>synchronizer: request_sync
Technical specifications
- The
synchronize
slot no longer synchronizes immediately. It becomes atry_sync
slot, that is auto-connected to the input timelines, and only synchronizes if the slotrequest_sync
has been called. - When the synchronisation occurs, the service "locks" itself so that every sync request is discarded.
- For simplicity, merge the
synchronization_skipped
with thesynchronization_done
signal. We do not need to make a distinction.
For clarity and simplicity, I propose to break the API and replace every occurrence of the current /synchronize
slot in the XML configurations by /request_sync
. No need to call try_sync
, this is done through auto connections.
Test plan
- Ideally, reproduce the failure case in a unit-test, and fix it thanks to this new design.
- Test modified applications.