1
0
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:
0O0o0oOoO00
2025-08-04 17:34:52 +08:00
parent 37bc31c237
commit dd1ba6c9f8

View File

@@ -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: