Hi all,
Here at MAX-IV, we have a lot of higher level devices that subscribe to change events from lower level devices (typically, valve devices subscribing to a PLC device).
One issue I have with the event subscription is that the event callback thread and a client request thread might run concurrently, since there is no implicit locking.
Therefore I’m using explicit locking but it is not a perfect solution; it is actually quite hard to maintain. For instance, the device can deadlock if those two threads end up waiting for the explicit lock and the monitor lock (the event callback thread might try to acquire the monitor lock if it pushes an event for instance).
A solution could be to have the monitor lock (called AutoTangoMonitor in C++) accessible via a device method:
def event_callback(self, event):
with self.get_monitor_lock() as lock:
self.process_event(event)
Event better, the device itself could provide a method for event subscription:
def init_device(self):
attr_proxy = AttributeProxy('a/b/c/d')
args = attr_proxy, EventType.CHANGE_EVENT, self.event_callback
self.subscribe_event(*args) # lock the callback automatically
The implementation of the method would look like:
def subscribe_event(self, attr_proxy, event_type, callback):
def safe_callback(event):
with self.get_monitor_lock():
return callback(event)
return attr_proxy.subscribe_event(event_type, safe_callback)
This is the best solution I could find, and doesn’t look too hard to implement. Please let me know if there is a better way to deal with that kind of issue. Otherwise, I’ll fill up a feature request.
Thanks,
Vincent