[Add] Add event engine
This commit is contained in:
parent
e3c22e3371
commit
9d3ec12695
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,10 +1,10 @@
|
|||||||
|
# Python
|
||||||
|
*.pyc
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.vscode
|
.vscode
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
# Python
|
# Temp
|
||||||
.pyc
|
|
||||||
.pyo
|
|
||||||
|
|
||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
|
0
vnpy/__init__.py
Normal file
0
vnpy/__init__.py
Normal file
1
vnpy/event/__init__.py
Normal file
1
vnpy/event/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from engine import Event, EventEngine, EVENT_TIMER
|
139
vnpy/event/engine.py
Normal file
139
vnpy/event/engine.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
from queue import Queue, Empty
|
||||||
|
from threading import Thread, Timer
|
||||||
|
from collections import defaultdict
|
||||||
|
from time import sleep
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
EVENT_TIMER = "eTimer"
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
self._process(event)
|
||||||
|
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(EVENT_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: str, 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: str, 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)
|
Loading…
Reference in New Issue
Block a user