看完了mainengine
的**,大概有乙個了解以後。我們在初始化mainengine
的時候,要傳入或者例項化乙個事件引擎物件。
按照慣例,我把所有的方法體摺疊,只保留類和方法,先大概對這個類要實現的功能有乙個基本的了解。然後再逐個深入。
class eventengine:
def __init__(self, interval: int = 1):
pass
def _run(self):
pass
def _process(self, event: event):
pass
def _run_timer(self):
pass
def start(self):
pass
def stop(self):
pass
def put(self, event: event):
pass
def register(self, type: str, handler: handlertype):
pass
def unregister(self, type: str, handler: handlertype):
pass
def register_general(self, handler: handlertype):
pass
def unregister_general(self, handler: handlertype):
pass
這個eventengine
看起來要比mainengin
有點貨,至少從方法名字上很難一目了然的猜測到方法的作用。腦海中浮過vc的訊息迴圈,或者c#的事件委託,又或者pyqt5的事件和插槽,不會是和那個機制類似的東東吧。
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 =
從初始化的**中可以看到,eventengine
用到了兩個執行緒thread
同時初始化了乙個佇列__queue
。
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:
我們找到handlertype
的定義
handlertype = callable[[event], none]
基本上可以理解到註冊乙個可以被**的方法,就是把這個方法的type和方法傳給eventengine然後,eventengine會把這個**方法儲存到_handlers[type]中的陣列中。
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)
正好和register相反的方法,把乙個事件從列表中移除。
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:
這個方法相當於把乙個不指定type的**方法放入_general_handlers,跟他相反的方法:unregister_general
def put(self, event: event):
"""put an event object into event queue.
"""self._queue.put(event)
這個是傳入乙個event,然後把這個event放入到乙個佇列中去
我們先來看看event這個類。
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
從以上的**,我們可以基本猜測在vnpy的事件引擎中,過來乙個型別的資料,然後把這個資料存放到佇列。然後再通過某種機制,定時的去呼叫那些通過regisiter進來的eventhandler。而什麼型別的資料進來,給什麼樣的handler**。應該是通過type去對應的。接下來,我們繼續深入。
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()
設定_active狀態,啟動或者阻塞執行緒。
def _run(self):
while self._active:
try:
event = self._queue.get(block=true, timeout=1)
self._process(event)
except empty:
pass
def _process(self, event: event):
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):
while self._active:
sleep(self._interval)
event = event(event_timer)
self.put(event)
通過核心****,我們豁然開朗。原來就是啟動了兩個執行緒,乙個執行緒不斷的迴圈把所有接受到的event
取出來傳送給需要它的handler
進行**,另外乙個執行緒不斷定時成event,然後這個event可以定時**某些handler
我總結成乙個
ruby gem bacon原始碼閱讀6
ruby gem bacon原始碼閱讀6 今天早上看些雜書,讀到 大學之路 中吳軍講,人生是馬拉松,因為很多人畢業後就不學習了,只要學習就有收穫。感覺很深 於是接著讀原始碼。靜下心來。用法是 require bacon describe a new array do before do ary ar...
FireMonkey 原始碼學習(6)
6 getglyph和getbaseline tfontglyphmanager是乙個抽象類,在不同平台上的實現是不同的,以windows為例,在fmx.fontglyphs.win.pas檔案中定義了 twinfontglyphmanager class tfontglyphmanager pro...
閱讀mutate原始碼學習dplyr
dplyr是r語言裡面處理資料資料非常好使的包,但是最近使用它解決一些問題時遇到了瓶頸,並且搜到的教程都特別基礎,所以我打算從原始碼的角度去找解決方案。為了理解dplyr mutate這個函式,我們需要借助乙個例項,分別思考mutate mtcars mutate mtcars,gear carb ...