device: lock computation of gestures and settings to prevent two threads from doing the same work

This commit is contained in:
Peter F. Patel-Schneider 2022-01-13 11:23:30 -05:00
parent a9c4950389
commit 22b99ecce7
1 changed files with 24 additions and 14 deletions

View File

@ -1,4 +1,5 @@
import errno as _errno import errno as _errno
import threading as _threading
from logging import INFO as _INFO from logging import INFO as _INFO
from logging import getLogger from logging import getLogger
@ -77,9 +78,11 @@ class Device:
self._firmware = None self._firmware = None
self._keys = None self._keys = None
self._gestures = None self._gestures = None
self._gestures_lock = _threading.Lock()
self._registers = None self._registers = None
self._settings = None self._settings = None
self._feature_settings_checked = False self._feature_settings_checked = False
self._settings_lock = _threading.Lock()
# Misc stuff that's irrelevant to any functionality, but may be # Misc stuff that's irrelevant to any functionality, but may be
# displayed in the UI and caching it here helps. # displayed in the UI and caching it here helps.
@ -288,8 +291,10 @@ class Device:
@property @property
def gestures(self): def gestures(self):
if not self._gestures: if not self._gestures:
if self.online and self.protocol >= 2.0: with self._gestures_lock:
self._gestures = _hidpp20.get_gestures(self) or () if not self._gestures:
if self.online and self.protocol >= 2.0:
self._gestures = _hidpp20.get_gestures(self) or ()
return self._gestures return self._gestures
@property @property
@ -304,19 +309,24 @@ class Device:
@property @property
def settings(self): def settings(self):
if not self._settings: if not self._settings:
self._settings = [] with self._settings_lock:
if self.persister and self.descriptor and self.descriptor.settings: if not self._settings:
for sclass in self.descriptor.settings: settings = []
try: if self.persister and self.descriptor and self.descriptor.settings:
setting = sclass.build(self) for sclass in self.descriptor.settings:
except Exception as e: # Do nothing if the device is offline try:
setting = None setting = sclass.build(self)
if self.online: except Exception as e: # Do nothing if the device is offline
raise e setting = None
if setting is not None: if self.online:
self._settings.append(setting) raise e
if setting is not None:
settings.append(setting)
self._settings = settings
if not self._feature_settings_checked: if not self._feature_settings_checked:
self._feature_settings_checked = _check_feature_settings(self, self._settings) with self._settings_lock:
if not self._feature_settings_checked:
self._feature_settings_checked = _check_feature_settings(self, self._settings)
return self._settings return self._settings
@property @property