mirror of
https://github.com/0O0o0oOoO00/Alas.git
synced 2026-05-14 15:59:25 +08:00
ref: refactor the way of handling vm interrupt in AzurLaneNetworkClient
This commit is contained in:
@@ -6,6 +6,40 @@ from module.gamefree.netpkg import *
|
||||
from module.logger import logger
|
||||
|
||||
|
||||
class VmInterruptEvent:
|
||||
def __init__(self):
|
||||
self.true_event = threading.Event()
|
||||
self.false_event = threading.Event()
|
||||
self.false_event.set()
|
||||
|
||||
def set_true(self):
|
||||
self.true_event.set()
|
||||
self.false_event.clear()
|
||||
|
||||
def set_false(self):
|
||||
self.true_event.clear()
|
||||
self.false_event.set()
|
||||
|
||||
def is_true(self):
|
||||
return self.true_event.is_set()
|
||||
|
||||
def is_false(self):
|
||||
return self.false_event.is_set()
|
||||
|
||||
def wait_until_true(self):
|
||||
self.true_event.wait()
|
||||
|
||||
def wait_until_false(self):
|
||||
self.false_event.wait()
|
||||
|
||||
def __enter__(self):
|
||||
self.wait_until_true()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.set_false()
|
||||
|
||||
|
||||
class AzurLaneNetworkClient:
|
||||
instance = None
|
||||
|
||||
@@ -13,8 +47,10 @@ class AzurLaneNetworkClient:
|
||||
self.task_queue = Queue()
|
||||
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.vm: Union[threading.Thread, None] = None
|
||||
self.vm_continue = threading.Event()
|
||||
self.vm_interrupt_event_queue = Queue()
|
||||
self.vm_exception: Union[Exception, None] = None
|
||||
self.vm_exception_event = VmInterruptEvent()
|
||||
self.vm_exit_request = threading.Event()
|
||||
|
||||
def __del__(self):
|
||||
self.vm_stop()
|
||||
@@ -39,9 +75,8 @@ class AzurLaneNetworkClient:
|
||||
pkg.event.set()
|
||||
|
||||
def vm_clear_task_queue(self):
|
||||
self.vm_interrupt()
|
||||
self.clear_task_queue()
|
||||
self.vm_resume()
|
||||
with self.vm_interrupt():
|
||||
self.clear_task_queue()
|
||||
|
||||
def vm_start(self):
|
||||
if self.vm is not None:
|
||||
@@ -49,22 +84,25 @@ class AzurLaneNetworkClient:
|
||||
return
|
||||
self.vm = threading.Thread(target=self.vm_thread)
|
||||
self.vm.start()
|
||||
self.vm_continue.set()
|
||||
|
||||
def vm_interrupt(self):
|
||||
self.vm_continue.clear()
|
||||
def vm_interrupt(self) -> VmInterruptEvent:
|
||||
if self.vm_exit_request.is_set():
|
||||
raise RuntimeError("Client vm is trying to exit")
|
||||
interrupt_event = VmInterruptEvent()
|
||||
self.vm_interrupt_event_queue.put(interrupt_event)
|
||||
return interrupt_event
|
||||
|
||||
def vm_resume(self):
|
||||
self.vm_continue.set()
|
||||
def vm_resume(self, interrupt_event):
|
||||
interrupt_event.set_false()
|
||||
|
||||
def vm_stop(self):
|
||||
self.vm_interrupt()
|
||||
self.clear_task_queue()
|
||||
self.queue_package(AzurLaneNetworkEndPackage())
|
||||
self.vm_resume()
|
||||
self.vm_exit_request.set()
|
||||
with self.vm_interrupt():
|
||||
self.clear_task_queue()
|
||||
self.queue_package(AzurLaneNetworkEndPackage())
|
||||
|
||||
def vm_wait_until_exception_handled(self):
|
||||
self.vm_continue.wait()
|
||||
self.vm_exception_event.wait_until_false()
|
||||
|
||||
def vm_get_exception(self) -> Exception:
|
||||
return self.vm_exception
|
||||
@@ -75,12 +113,15 @@ class AzurLaneNetworkClient:
|
||||
def vm_set_exception(self, e):
|
||||
self.vm_exception = e
|
||||
|
||||
def vm_clear_exception(self):
|
||||
def vm_exception_handled_and_resume(self):
|
||||
self.vm_exception = None
|
||||
self.vm_exception_event.set_false()
|
||||
|
||||
def vm_ensure_continue(self):
|
||||
if not self.vm_continue.is_set():
|
||||
self.vm_continue.wait()
|
||||
while not self.vm_interrupt_event_queue.empty():
|
||||
interrupt_event = self.vm_interrupt_event_queue.get()
|
||||
interrupt_event.set_true()
|
||||
interrupt_event.wait_until_false()
|
||||
|
||||
def vm_thread(self):
|
||||
while 1:
|
||||
@@ -95,15 +136,24 @@ class AzurLaneNetworkClient:
|
||||
pkg.event.set()
|
||||
except Exception as e:
|
||||
self.vm_set_exception(e)
|
||||
self.vm_interrupt()
|
||||
self.vm_exception_event.set_true()
|
||||
pkg.event.set()
|
||||
self.vm_wait_until_exception_handled()
|
||||
else:
|
||||
logger.warning(f"Unknown net package class: {type(pkg).__name__}")
|
||||
|
||||
def queue_package(self, pkg):
|
||||
if self.vm_exit_request.is_set():
|
||||
raise RuntimeError("Client vm is trying to exit")
|
||||
self.task_queue.put(pkg)
|
||||
|
||||
def queue_packages(self, *pkgs):
|
||||
if self.vm_exit_request.is_set():
|
||||
raise RuntimeError("Client vm is trying to exit")
|
||||
with self.vm_interrupt():
|
||||
for i in pkgs:
|
||||
self.task_queue.put(i)
|
||||
|
||||
@staticmethod
|
||||
def get_instance() -> "AzurLaneNetworkClient":
|
||||
if AzurLaneNetworkClient.instance is None:
|
||||
|
||||
Reference in New Issue
Block a user