以太坊中的事件机制Feed
? ? 以太坊的事件框架,存在于目錄go-ethereum/event中,它有兩種事件框架實(shí)現(xiàn),一種叫TypeMux(go-ethereum/event/event.go),現(xiàn)在已經(jīng)基本棄用;另外一種叫Feed(go-ethereum/event/feed.go),?它是目前主要使用的對象。取代了前面說的event.go內(nèi)部的TypeMux。
? ? 以太坊的事件框架會把所有的訂閱者放到一個(gè)集合中,每當(dāng)事件框架收到某個(gè)事件的時(shí)候,就把通知所有訂閱該事件的所有訂閱者。由于TypeMux有可能會阻塞,所以通知訂閱者可能會延時(shí)很久,估計(jì)這就是為什么棄用的原因吧。而Feed基本不會阻塞,一般會及時(shí)的把事件通知給訂閱者,但需要給每種事件創(chuàng)建一個(gè)Feed,訂閱或者發(fā)送事件則需要在不同的Feed上處理。下面主要介紹一下Feed的實(shí)現(xiàn)方式。
? ??Feed是一對多的事件框架。
-
? ? 數(shù)據(jù)結(jié)構(gòu)
? ? Feed的主要函數(shù)以及數(shù)據(jù)結(jié)構(gòu)如下:
? ? Subscribe以及Send函數(shù)是包外可以調(diào)用的函數(shù)。
Subscribe函數(shù)添加一個(gè)訂閱
func (f *Feed) Send(value interface{}) (nsent int)Send函數(shù)發(fā)送一個(gè)訂閱事件。
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函數(shù)只執(zhí)行一次;sendLock是 “Send函數(shù)的鎖。removeSub是“Send”以及“remove"之間“通訊”接口。sendCases是訂閱者列表。inbox是剛剛加入的訂閱者列表(Send函數(shù)會將inbox的訂閱者移動到sendCases中);closed標(biāo)識此訂閱事件的狀態(tài)。
? ? feedSub是Subscription的一種實(shí)現(xiàn)。Feed是管理各種feedSub。
? ? ?Subscription是個(gè)接口,定義在event/subscription.go文件中:
? ? Subscription提供兩個(gè)函數(shù):Err函數(shù)負(fù)責(zé)出錯(cuò)處理,Unsubscribe函數(shù)停止訂閱。
Unsubscribe() 實(shí)現(xiàn)了訂閱者退訂某個(gè)事件;訂閱事件的函數(shù)在上邊已經(jīng)實(shí)現(xiàn)了。
-
實(shí)現(xiàn)方式
? ? 實(shí)際運(yùn)用中,我們主要的流程,就是訂閱,發(fā)送事件,接收事件,取消訂閱。
? ? 訂閱,訂閱時(shí)需要一個(gè)channel作為參數(shù)傳入。訂閱函數(shù)也會校驗(yàn)傳入的參數(shù)是否為chan以及通道的方向;然后構(gòu)造一個(gè)feedSub數(shù)據(jù)作為返回值;?使用傳入的channel生成了SelectCase,放入inbox,即將新加入的訂閱者放入inbox里。?
?
? ? 取消訂閱,一般注冊完成后,訂閱者會獲取一個(gè)Subscription,可以通過它取消訂閱和讀取通道錯(cuò)誤。這時(shí),訂閱者會從inbox和sendCases中都被刪除。
? ? 發(fā)布事件,調(diào)用Feed.Send(chan x),通過加鎖確保本類型事件只有一個(gè)發(fā)送協(xié)程正在進(jìn)行,然后校驗(yàn)事件類型是否匹配,Feed會嘗試給每個(gè)訂閱者發(fā)送事件,如果訂閱者阻塞,Feed就繼續(xù)嘗試給下一個(gè)訂閱者發(fā)送,直到給每個(gè)訂閱者發(fā)送事件,返回發(fā)送該事件的數(shù)量。
? ? 接收事件,訂閱者通過讀取chan里的數(shù)據(jù),實(shí)現(xiàn)事件的接收。
-
如何使用
? ? ? 我們設(shè)置了事件bigevent,創(chuàng)建了feed,然后訂閱feed;開啟協(xié)程監(jiān)聽通道,看是否有事件推送,等到通多關(guān)閉后,取消訂閱;
?
?
?
總結(jié)
以上是生活随笔為你收集整理的以太坊中的事件机制Feed的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: isFile()exists() isD
- 下一篇: 使用ffmpeg实现视频连接