From adf0f3c570f5bf6092fd12a74153a11aa80b64b3 Mon Sep 17 00:00:00 2001 From: David Hammer <dhammer@mailbox.org> Date: Fri, 1 Apr 2022 18:21:39 +0200 Subject: [PATCH] Move expensive buffer changes to background to avoid timeouts --- src/calng/base_correction.py | 13 +++++++++---- src/calng/utils.py | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/calng/base_correction.py b/src/calng/base_correction.py index b451c5ee..e498d34a 100644 --- a/src/calng/base_correction.py +++ b/src/calng/base_correction.py @@ -709,8 +709,7 @@ class BaseCorrection(PythonDevice): update = self._prereconfigure_update_hash if update.has("frameFilter"): - with self._buffer_lock: - self._update_frame_filter() + self._lock_and_update_in_background(self._update_frame_filter) elif any( update.has(shape_param) for shape_param in ( @@ -721,11 +720,17 @@ class BaseCorrection(PythonDevice): "frameFilter", ) ): - with self._buffer_lock: - self._update_buffers() + self._lock_and_update_in_background(self._update_buffers) # TODO: only call this if they are changed (is cheap, though) self._update_correction_flags() + def _lock_and_update_in_background(self, method): + # TODO: securely handle errors (postReconfigure may succeed and device state not) + def runner(): + with self._buffer_lock, utils.StateContext(self, State.CHANGING): + method() + threading.Thread(target=runner, daemon=True).start() + def loadMostRecentConstants(self): self.flush_constants() self.calcat_friend.flush_constants() diff --git a/src/calng/utils.py b/src/calng/utils.py index b14e36b8..c24502a8 100644 --- a/src/calng/utils.py +++ b/src/calng/utils.py @@ -279,6 +279,25 @@ class Stopwatch: return f"{self.name}: {self.elapsed():.3f} s" +class StateContext: + """What if device state was a stack?""" + + def __init__(self, device, new_state, revert_to=None): + self.device = device + if revert_to is None: + revert_to = device.get("state") + self.revert_to = revert_to + self.new_state = new_state + + def __enter__(self): + if self.new_state is not self.revert_to: + self.device.updateState(self.new_state) + + def __exit__(self, t, v, tb): + if self.new_state is not self.revert_to: + self.device.updateState(self.revert_to) + + class TrainRatioTracker: """Measure how many percent of recent train IDs (from contiguous set) were seen -- GitLab