toxygen/toxygen/middleware/threads.py

173 lines
4.7 KiB
Python

from bootstrap.bootstrap import *
import threading
import queue
from utils import util
import time
from PyQt5 import QtCore
# -----------------------------------------------------------------------------------------------------------------
# Base threads
# -----------------------------------------------------------------------------------------------------------------
class BaseThread(threading.Thread):
def __init__(self):
super().__init__()
self._stop_thread = False
def stop_thread(self):
self._stop_thread = True
self.join()
class BaseQThread(QtCore.QThread):
def __init__(self):
super().__init__()
self._stop_thread = False
def stop_thread(self):
self._stop_thread = True
self.wait()
# -----------------------------------------------------------------------------------------------------------------
# Toxcore threads
# -----------------------------------------------------------------------------------------------------------------
class InitThread(BaseThread):
def __init__(self, tox, plugin_loader, settings, is_first_start):
super().__init__()
self._tox, self._plugin_loader, self._settings = tox, plugin_loader, settings
self._is_first_start = is_first_start
def run(self):
if self._is_first_start:
# download list of nodes if needed
download_nodes_list(self._settings)
# start plugins
self._plugin_loader.load()
# bootstrap
try:
for data in generate_nodes():
if self._stop_thread:
return
self._tox.bootstrap(*data)
self._tox.add_tcp_relay(*data)
except:
pass
for _ in range(10):
if self._stop_thread:
return
time.sleep(1)
while not self._tox.self_get_connection_status():
try:
for data in generate_nodes(None):
if self._stop_thread:
return
self._tox.bootstrap(*data)
self._tox.add_tcp_relay(*data)
except:
pass
finally:
time.sleep(5)
class ToxIterateThread(BaseQThread):
def __init__(self, tox):
super().__init__()
self._tox = tox
def run(self):
while not self._stop_thread:
self._tox.iterate()
time.sleep(self._tox.iteration_interval() / 1000)
class ToxAVIterateThread(BaseQThread):
def __init__(self, toxav):
super().__init__()
self._toxav = toxav
def run(self):
while not self._stop_thread:
self._toxav.iterate()
time.sleep(self._toxav.iteration_interval() / 1000)
# -----------------------------------------------------------------------------------------------------------------
# File transfers thread
# -----------------------------------------------------------------------------------------------------------------
class FileTransfersThread(BaseQThread):
def __init__(self):
super().__init__()
self._queue = queue.Queue()
self._timeout = 0.01
def execute(self, func, *args, **kwargs):
self._queue.put((func, args, kwargs))
def run(self):
while not self._stop_thread:
try:
func, args, kwargs = self._queue.get(timeout=self._timeout)
func(*args, **kwargs)
except queue.Empty:
pass
except queue.Full:
util.log('Queue is full in _thread')
except Exception as ex:
util.log('Exception in _thread: ' + str(ex))
_thread = FileTransfersThread()
def start_file_transfer_thread():
_thread.start()
def stop_file_transfer_thread():
_thread.stop_thread()
def execute(func, *args, **kwargs):
_thread.execute(func, *args, **kwargs)
# -----------------------------------------------------------------------------------------------------------------
# Invoking in main thread
# -----------------------------------------------------------------------------------------------------------------
class InvokeEvent(QtCore.QEvent):
EVENT_TYPE = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())
def __init__(self, fn, *args, **kwargs):
QtCore.QEvent.__init__(self, InvokeEvent.EVENT_TYPE)
self.fn = fn
self.args = args
self.kwargs = kwargs
class Invoker(QtCore.QObject):
def event(self, event):
event.fn(*event.args, **event.kwargs)
return True
_invoker = Invoker()
def invoke_in_main_thread(fn, *args, **kwargs):
QtCore.QCoreApplication.postEvent(_invoker, InvokeEvent(fn, *args, **kwargs))