use Threading.Event object to terminate producer

This commit is contained in:
onyx-and-iris 2023-08-04 23:13:54 +01:00
parent 09cb62ecfa
commit 103355d265
4 changed files with 21 additions and 12 deletions

View File

@ -210,7 +210,7 @@ class BusLevel(IRemote):
def fget(x): def fget(x):
return round(20 * log(x, 10), 1) if x > 0 else -200.0 return round(20 * log(x, 10), 1) if x > 0 else -200.0
if self._remote.running and self._remote.event.ldirty: if not self._remote.stopped() and self._remote.event.ldirty:
vals = self._remote.cache["bus_level"][self.range[0] : self.range[-1]] vals = self._remote.cache["bus_level"][self.range[0] : self.range[-1]]
else: else:
vals = [self._remote.get_level(mode, i) for i in range(*self.range)] vals = [self._remote.get_level(mode, i) for i in range(*self.range)]
@ -232,7 +232,7 @@ class BusLevel(IRemote):
Expected to be used in a callback only. Expected to be used in a callback only.
""" """
if self._remote.running: if not self._remote.stopped():
return any(self._remote._bus_comp[self.range[0] : self.range[-1]]) return any(self._remote._bus_comp[self.range[0] : self.range[-1]])
is_updated = isdirty is_updated = isdirty

View File

@ -1,5 +1,6 @@
import ctypes as ct import ctypes as ct
import logging import logging
import threading
import time import time
from abc import abstractmethod from abc import abstractmethod
from queue import Queue from queue import Queue
@ -28,11 +29,12 @@ class Remote(CBindings):
self.cache = {} self.cache = {}
self.midi = Midi() self.midi = Midi()
self.subject = self.observer = Subject() self.subject = self.observer = Subject()
self.running = False
self.event = Event( self.event = Event(
{k: kwargs.pop(k) for k in ("pdirty", "mdirty", "midi", "ldirty")} {k: kwargs.pop(k) for k in ("pdirty", "mdirty", "midi", "ldirty")}
) )
self.gui = VmGui() self.gui = VmGui()
self.stop_event = threading.Event()
self.stop_event.clear()
self.logger = logger.getChild(self.__class__.__name__) self.logger = logger.getChild(self.__class__.__name__)
for attr, val in kwargs.items(): for attr, val in kwargs.items():
@ -52,16 +54,18 @@ class Remote(CBindings):
def init_thread(self): def init_thread(self):
"""Starts updates thread.""" """Starts updates thread."""
self.running = True
self.event.info() self.event.info()
self.logger.debug("initiating events thread") self.logger.debug("initiating events thread")
queue = Queue() queue = Queue()
self.updater = Updater(self, queue) self.updater = Updater(self, queue)
self.updater.start() self.updater.start()
self.producer = Producer(self, queue) self.producer = Producer(self, queue, self.stop_event)
self.producer.start() self.producer.start()
def stopped(self):
return self.stop_event.is_set()
def login(self) -> None: def login(self) -> None:
"""Login to the API, initialize dirty parameters""" """Login to the API, initialize dirty parameters"""
self.gui.launched = self.call(self.bind_login, ok=(0, 1)) == 0 self.gui.launched = self.call(self.bind_login, ok=(0, 1)) == 0
@ -331,9 +335,10 @@ class Remote(CBindings):
self.logger.info(f"Profile '{name}' applied!") self.logger.info(f"Profile '{name}' applied!")
def end_thread(self): def end_thread(self):
if self.running: if not self.stopped():
self.logger.debug("events thread shutdown started") self.logger.debug("events thread shutdown started")
self.running = False self.stop_event.set()
self.producer.join() # wait for producer thread to complete cycle
def logout(self) -> None: def logout(self) -> None:
"""Logout of the API""" """Logout of the API"""

View File

@ -415,7 +415,7 @@ class StripLevel(IRemote):
def fget(x): def fget(x):
return round(20 * log(x, 10), 1) if x > 0 else -200.0 return round(20 * log(x, 10), 1) if x > 0 else -200.0
if self._remote.running and self._remote.event.ldirty: if not self._remote.stopped() and self._remote.event.ldirty:
vals = self._remote.cache["strip_level"][self.range[0] : self.range[-1]] vals = self._remote.cache["strip_level"][self.range[0] : self.range[-1]]
else: else:
vals = [self._remote.get_level(mode, i) for i in range(*self.range)] vals = [self._remote.get_level(mode, i) for i in range(*self.range)]
@ -448,7 +448,7 @@ class StripLevel(IRemote):
Expected to be used in a callback only. Expected to be used in a callback only.
""" """
if self._remote.running: if not self._remote.stopped():
return any(self._remote._strip_comp[self.range[0] : self.range[-1]]) return any(self._remote._strip_comp[self.range[0] : self.range[-1]])
is_updated = isdirty is_updated = isdirty

View File

@ -10,14 +10,18 @@ logger = logging.getLogger(__name__)
class Producer(threading.Thread): class Producer(threading.Thread):
"""Continously send job queue to the Updater thread at a rate of self._remote.ratelimit.""" """Continously send job queue to the Updater thread at a rate of self._remote.ratelimit."""
def __init__(self, remote, queue): def __init__(self, remote, queue, stop_event):
super().__init__(name="producer", daemon=True) super().__init__(name="producer", daemon=False)
self._remote = remote self._remote = remote
self.queue = queue self.queue = queue
self.stop_event = stop_event
self.logger = logger.getChild(self.__class__.__name__) self.logger = logger.getChild(self.__class__.__name__)
def stopped(self):
return self.stop_event.is_set()
def run(self): def run(self):
while self._remote.running: while not self.stopped():
if self._remote.event.pdirty: if self._remote.event.pdirty:
self.queue.put("pdirty") self.queue.put("pdirty")
if self._remote.event.mdirty: if self._remote.event.mdirty: