2022-07-06 19:31:59 -04:00
|
|
|
import abc
|
|
|
|
import logging
|
|
|
|
import threading
|
|
|
|
|
2022-11-22 13:19:28 -05:00
|
|
|
import wrapt
|
|
|
|
|
2022-07-06 19:31:59 -04:00
|
|
|
|
|
|
|
LOG = logging.getLogger("APRSD")
|
|
|
|
|
|
|
|
|
|
|
|
class APRSDThreadList:
|
|
|
|
"""Singleton class that keeps track of application wide threads."""
|
|
|
|
|
|
|
|
_instance = None
|
|
|
|
|
|
|
|
threads_list = []
|
2022-11-22 13:19:28 -05:00
|
|
|
lock = threading.Lock()
|
2022-07-06 19:31:59 -04:00
|
|
|
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
|
|
if cls._instance is None:
|
|
|
|
cls._instance = super().__new__(cls)
|
|
|
|
cls.threads_list = []
|
|
|
|
return cls._instance
|
|
|
|
|
2022-11-22 13:19:28 -05:00
|
|
|
@wrapt.synchronized(lock)
|
2022-07-06 19:31:59 -04:00
|
|
|
def add(self, thread_obj):
|
2022-11-22 13:19:28 -05:00
|
|
|
self.threads_list.append(thread_obj)
|
2022-07-06 19:31:59 -04:00
|
|
|
|
2022-11-22 13:19:28 -05:00
|
|
|
@wrapt.synchronized(lock)
|
2022-07-06 19:31:59 -04:00
|
|
|
def remove(self, thread_obj):
|
2022-11-22 13:19:28 -05:00
|
|
|
self.threads_list.remove(thread_obj)
|
2022-07-06 19:31:59 -04:00
|
|
|
|
2022-11-22 13:19:28 -05:00
|
|
|
@wrapt.synchronized(lock)
|
2022-07-06 19:31:59 -04:00
|
|
|
def stop_all(self):
|
|
|
|
"""Iterate over all threads and call stop on them."""
|
2022-11-22 13:19:28 -05:00
|
|
|
for th in self.threads_list:
|
|
|
|
LOG.info(f"Stopping Thread {th.name}")
|
2022-12-15 17:23:54 -05:00
|
|
|
if hasattr(th, "packet"):
|
|
|
|
LOG.info(F"{th.name} packet {th.packet}")
|
2022-11-22 13:19:28 -05:00
|
|
|
th.stop()
|
2022-07-06 19:31:59 -04:00
|
|
|
|
2022-11-22 13:19:28 -05:00
|
|
|
@wrapt.synchronized(lock)
|
2022-07-06 19:31:59 -04:00
|
|
|
def __len__(self):
|
2022-11-22 13:19:28 -05:00
|
|
|
return len(self.threads_list)
|
2022-07-06 19:31:59 -04:00
|
|
|
|
|
|
|
|
|
|
|
class APRSDThread(threading.Thread, metaclass=abc.ABCMeta):
|
2022-11-22 13:19:28 -05:00
|
|
|
|
2022-07-06 19:31:59 -04:00
|
|
|
def __init__(self, name):
|
|
|
|
super().__init__(name=name)
|
|
|
|
self.thread_stop = False
|
|
|
|
APRSDThreadList().add(self)
|
|
|
|
|
2022-11-22 13:19:28 -05:00
|
|
|
def _should_quit(self):
|
|
|
|
""" see if we have a quit message from the global queue."""
|
|
|
|
if self.thread_stop:
|
|
|
|
return True
|
|
|
|
|
2022-07-06 19:31:59 -04:00
|
|
|
def stop(self):
|
|
|
|
self.thread_stop = True
|
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def loop(self):
|
|
|
|
pass
|
|
|
|
|
2022-11-22 13:19:28 -05:00
|
|
|
def _cleanup(self):
|
|
|
|
"""Add code to subclass to do any cleanup"""
|
|
|
|
|
2022-07-06 19:31:59 -04:00
|
|
|
def run(self):
|
|
|
|
LOG.debug("Starting")
|
2022-11-22 13:19:28 -05:00
|
|
|
while not self._should_quit():
|
2022-07-06 19:31:59 -04:00
|
|
|
can_loop = self.loop()
|
|
|
|
if not can_loop:
|
|
|
|
self.stop()
|
2022-11-22 13:19:28 -05:00
|
|
|
self._cleanup()
|
2022-07-06 19:31:59 -04:00
|
|
|
APRSDThreadList().remove(self)
|
|
|
|
LOG.debug("Exiting")
|