以太坊中的事件机制Feed
? ? 以太坊的事件框架,存在于目錄go-ethereum/event中,它有兩種事件框架實現,一種叫TypeMux(go-ethereum/event/event.go),現在已經基本棄用;另外一種叫Feed(go-ethereum/event/feed.go),?它是目前主要使用的對象。取代了前面說的event.go內部的TypeMux。
? ? 以太坊的事件框架會把所有的訂閱者放到一個集合中,每當事件框架收到某個事件的時候,就把通知所有訂閱該事件的所有訂閱者。由于TypeMux有可能會阻塞,所以通知訂閱者可能會延時很久,估計這就是為什么棄用的原因吧。而Feed基本不會阻塞,一般會及時的把事件通知給訂閱者,但需要給每種事件創建一個Feed,訂閱或者發送事件則需要在不同的Feed上處理。下面主要介紹一下Feed的實現方式。
? ??Feed是一對多的事件框架。
-
? ? 數據結構
? ? Feed的主要函數以及數據結構如下:
? ? Subscribe以及Send函數是包外可以調用的函數。
Subscribe函數添加一個訂閱
func (f *Feed) Send(value interface{}) (nsent int)Send函數發送一個訂閱事件。
type Feed struct {once sync.Once // ensures that init only runs oncesendLock chan struct{} // sendLock has a one-element buffer and is empty when held.It protects sendCases.removeSub chan interface{} // interrupts SendsendCases caseList // the active set of select cases used by Send// The inbox holds newly subscribed channels until they are added to sendCases.mu sync.Mutexinbox caseListetype reflect.Typeclosed bool }
once保證init函數只執行一次;sendLock是 “Send函數的鎖。removeSub是“Send”以及“remove"之間“通訊”接口。sendCases是訂閱者列表。inbox是剛剛加入的訂閱者列表(Send函數會將inbox的訂閱者移動到sendCases中);closed標識此訂閱事件的狀態。
? ? feedSub是Subscription的一種實現。Feed是管理各種feedSub。
? ? ?Subscription是個接口,定義在event/subscription.go文件中:
? ? Subscription提供兩個函數:Err函數負責出錯處理,Unsubscribe函數停止訂閱。
Unsubscribe() 實現了訂閱者退訂某個事件;訂閱事件的函數在上邊已經實現了。
-
實現方式
? ? 實際運用中,我們主要的流程,就是訂閱,發送事件,接收事件,取消訂閱。
? ? 訂閱,訂閱時需要一個channel作為參數傳入。訂閱函數也會校驗傳入的參數是否為chan以及通道的方向;然后構造一個feedSub數據作為返回值;?使用傳入的channel生成了SelectCase,放入inbox,即將新加入的訂閱者放入inbox里。?
?
? ? 取消訂閱,一般注冊完成后,訂閱者會獲取一個Subscription,可以通過它取消訂閱和讀取通道錯誤。這時,訂閱者會從inbox和sendCases中都被刪除。
? ? 發布事件,調用Feed.Send(chan x),通過加鎖確保本類型事件只有一個發送協程正在進行,然后校驗事件類型是否匹配,Feed會嘗試給每個訂閱者發送事件,如果訂閱者阻塞,Feed就繼續嘗試給下一個訂閱者發送,直到給每個訂閱者發送事件,返回發送該事件的數量。
? ? 接收事件,訂閱者通過讀取chan里的數據,實現事件的接收。
-
如何使用
? ? ? 我們設置了事件bigevent,創建了feed,然后訂閱feed;開啟協程監聽通道,看是否有事件推送,等到通多關閉后,取消訂閱;
?
?
?
總結
以上是生活随笔為你收集整理的以太坊中的事件机制Feed的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: isFile()exists() isD
- 下一篇: 使用ffmpeg实现视频连接