Files
pepperplus-ri/state.py
Twirre Meulenbelt 2132a74321 fix: allow access to state's exit_event while exiting
When exiting, the state's `is_initialized` flag is unset. Noticeable on Windows, when a thread tried to access the state's `exit_event` property to check whether it had been set, it would complain that the state was no longer initialized. Now, even when no longer initialized, if the `exit_event` is set, it will not raise an error when accessing this attribute.

ref: N25B-119
2025-10-01 17:34:51 +02:00

53 lines
1.8 KiB
Python

import signal
import threading
class State(object):
"""
Do not create an instance of this class directly: use the instance `state` below. This state must be initiated once,
probably when your program starts.
This class is used to share state between threads. For example, when the program is quit, that all threads can
detect this via the `exit_event` property being set.
"""
def __init__(self):
self.is_initialized = False
self.exit_event = None
def initialize(self):
if self.is_initialized:
print("Already initialized")
return
self.exit_event = threading.Event()
def handle_exit(_, __):
print("Exiting.")
self.exit_event.set()
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
self.is_initialized = True
def deinitialize(self):
if not self.is_initialized: return
self.is_initialized = False
def __getattribute__(self, name):
# Enforce that the state is initialized before accessing any property (aside from the basic ones)
if name in ("initialize", "deinitialize", "is_initialized", "__dict__", "__class__"):
return object.__getattribute__(self, name)
if not object.__getattribute__(self, "is_initialized"):
# Special case for the exit_event: if the event is set, return it without an error
if name == "exit_event":
exit_event = object.__getattribute__(self, "exit_event")
if exit_event and exit_event.is_set(): return exit_event
raise RuntimeError("State must be initialized before accessing '%s'" % name)
return object.__getattribute__(self, name)
# Must call `.initialize` before use
state = State()