You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.6 KiB
165 lines
4.6 KiB
"""
|
|
Event-driven framework of vn.py framework.
|
|
"""
|
|
|
|
from collections import defaultdict
|
|
from queue import Empty, Queue
|
|
from threading import Thread
|
|
from time import sleep
|
|
from typing import Any, Callable
|
|
from abc import ABC
|
|
from ..common.datastruct import Event
|
|
from ..common.constant import EventType
|
|
|
|
# class Event:
|
|
# """
|
|
# Event object consists of a type string which is used
|
|
# by event engine for distributing event, and a data
|
|
# object which contains the real data.
|
|
# """
|
|
|
|
# def __init__(self, type: str, data: Any = None):
|
|
# """"""
|
|
# self.type = type
|
|
# self.data = data
|
|
|
|
|
|
# Defines handler function to be used in event engine.
|
|
HandlerType = Callable[[Event], None]
|
|
|
|
|
|
class EventEngine:
|
|
"""
|
|
Event engine distributes event object based on its type
|
|
to those handlers registered.
|
|
|
|
It also generates timer event by every interval seconds,
|
|
which can be used for timing purpose.
|
|
"""
|
|
|
|
def __init__(self, interval: int = 1):
|
|
"""
|
|
Timer event is generated every 1 second by default, if
|
|
interval not specified.
|
|
"""
|
|
self._interval = interval
|
|
self._queue = Queue()
|
|
self._active = False
|
|
self._thread = Thread(target=self._run)
|
|
self._timer = Thread(target=self._run_timer)
|
|
self._handlers = defaultdict(list)
|
|
self._general_handlers = []
|
|
|
|
def _run(self):
|
|
"""
|
|
Get event from queue and then process it.
|
|
"""
|
|
while self._active:
|
|
try:
|
|
event = self._queue.get(block=True, timeout=1)
|
|
if event.event_type in self._handlers:
|
|
[handler(event)
|
|
for handler in self._handlers[event.event_type]]
|
|
except Empty:
|
|
pass
|
|
|
|
# def _process(self, event: Event):
|
|
# """
|
|
# First ditribute event to those handlers registered listening
|
|
# to this type.
|
|
|
|
# Then distrubute event to those general handlers which listens
|
|
# to all types.
|
|
# """
|
|
# if event.type in self._handlers:
|
|
# [handler(event) for handler in self._handlers[event.type]]
|
|
|
|
# if self._general_handlers:
|
|
# [handler(event) for handler in self._general_handlers]
|
|
|
|
def _run_timer(self):
|
|
"""
|
|
Sleep by interval second(s) and then generate a timer event.
|
|
"""
|
|
while self._active:
|
|
sleep(self._interval)
|
|
event = Event(type=EventType.TIMER)
|
|
self.put(event)
|
|
|
|
def start(self):
|
|
"""
|
|
Start event engine to process events and generate timer events.
|
|
"""
|
|
self._active = True
|
|
self._thread.start()
|
|
self._timer.start()
|
|
|
|
def stop(self):
|
|
"""
|
|
Stop event engine.
|
|
"""
|
|
self._active = False
|
|
self._timer.join()
|
|
self._thread.join()
|
|
|
|
def put(self, event: Event):
|
|
"""
|
|
Put an event object into event queue.
|
|
"""
|
|
self._queue.put(event)
|
|
|
|
def register(self, type: EventType, handler: HandlerType):
|
|
"""
|
|
Register a new handler function for a specific event type. Every
|
|
function can only be registered once for each event type.
|
|
"""
|
|
handler_list = self._handlers[type]
|
|
if handler not in handler_list:
|
|
handler_list.append(handler)
|
|
|
|
def unregister(self, type: EventType, handler: HandlerType):
|
|
"""
|
|
Unregister an existing handler function from event engine.
|
|
"""
|
|
handler_list = self._handlers[type]
|
|
|
|
if handler in handler_list:
|
|
handler_list.remove(handler)
|
|
|
|
if not handler_list:
|
|
self._handlers.pop(type)
|
|
|
|
def register_general(self, handler: HandlerType):
|
|
"""
|
|
Register a new handler function for all event types. Every
|
|
function can only be registered once for each event type.
|
|
"""
|
|
if handler not in self._general_handlers:
|
|
self._general_handlers.append(handler)
|
|
|
|
def unregister_general(self, handler: HandlerType):
|
|
"""
|
|
Unregister an existing general handler function.
|
|
"""
|
|
if handler in self._general_handlers:
|
|
self._general_handlers.remove(handler)
|
|
|
|
|
|
class BaseEngine(ABC):
|
|
"""
|
|
Abstract class for implementing an function engine.
|
|
"""
|
|
|
|
def __init__(self, event_engine: EventEngine = None):
|
|
""""""
|
|
if event_engine:
|
|
self.event_engine = event_engine
|
|
else:
|
|
self.event_engine = EventEngine()
|
|
|
|
def start(self):
|
|
self.event_engine.start()
|
|
|
|
def close(self):
|
|
""""""
|
|
pass
|
|
|