日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

以太坊中的事件机制Feed

發(fā)布時(shí)間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 以太坊中的事件机制Feed 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? 以太坊的事件框架,存在于目錄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ù)。

func (f *Feed) Subscribe(channel interface{}) Subscription

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)。

type feedSub struct {feed *Feedchannel reflect.ValueerrOnce sync.Onceerr chan error }

? ? feedSub是Subscription的一種實(shí)現(xiàn)。Feed是管理各種feedSub。

? ? ?Subscription是個(gè)接口,定義在event/subscription.go文件中:
? ? Subscription提供兩個(gè)函數(shù):Err函數(shù)負(fù)責(zé)出錯(cuò)處理,Unsubscribe函數(shù)停止訂閱。

func (sub *feedSub) Unsubscribe()

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)事件的接收。

  • 如何使用

package mainimport ("fmt""sync""github.com/ethereum/go-ethereum/event" )func main() {type bigevent struct{ number int }var f event.Feedvar wg sync.WaitGroupch := make(chan bitevent)sub := feed.Subscribe(ch)wg.Add(1)go func() {defer wg.Done()for event := range ch {fmt.Printf("Received: %#v\n", event.number)}sub.Unsubscribe()}()feed.Send(bigevent{5})close(ch)wg.Wait() }

? ? ? 我們設(shè)置了事件bigevent,創(chuàng)建了feed,然后訂閱feed;開啟協(xié)程監(jiān)聽通道,看是否有事件推送,等到通多關(guān)閉后,取消訂閱;

?

?

?

總結(jié)

以上是生活随笔為你收集整理的以太坊中的事件机制Feed的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。