github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/event/event.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2014 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 //包事件处理对实时事件的订阅。 26 package event 27 28 import ( 29 "errors" 30 "fmt" 31 "reflect" 32 "sync" 33 "time" 34 ) 35 36 //typemuxevent是一个推送到订户的带有时间标签的通知。 37 type TypeMuxEvent struct { 38 Time time.Time 39 Data interface{} 40 } 41 42 //typemux将事件发送给已注册的接收者。接收器可以 43 //注册以处理特定类型的事件。任何操作 44 //在mux停止后调用将返回errmuxClosed。 45 // 46 //零值已准备好使用。 47 // 48 //已弃用:使用源 49 type TypeMux struct { 50 mutex sync.RWMutex 51 subm map[reflect.Type][]*TypeMuxSubscription 52 stopped bool 53 } 54 55 //在已关闭的typemux上发布时返回errmuxClosed。 56 var ErrMuxClosed = errors.New("event: mux closed") 57 58 //订阅为给定类型的事件创建订阅。这个 59 //订阅的频道在取消订阅时关闭 60 //或者MUX关闭。 61 func (mux *TypeMux) Subscribe(types ...interface{}) *TypeMuxSubscription { 62 sub := newsub(mux) 63 mux.mutex.Lock() 64 defer mux.mutex.Unlock() 65 if mux.stopped { 66 //将状态设置为“已关闭”,以便在此之后调用Unsubscribe 67 //呼叫将短路。 68 sub.closed = true 69 close(sub.postC) 70 } else { 71 if mux.subm == nil { 72 mux.subm = make(map[reflect.Type][]*TypeMuxSubscription) 73 } 74 for _, t := range types { 75 rtyp := reflect.TypeOf(t) 76 oldsubs := mux.subm[rtyp] 77 if find(oldsubs, sub) != -1 { 78 panic(fmt.Sprintf("event: duplicate type %s in Subscribe", rtyp)) 79 } 80 subs := make([]*TypeMuxSubscription, len(oldsubs)+1) 81 copy(subs, oldsubs) 82 subs[len(oldsubs)] = sub 83 mux.subm[rtyp] = subs 84 } 85 } 86 return sub 87 } 88 89 //Post向为给定类型注册的所有接收器发送事件。 90 //如果MUX已停止,则返回errmuxClosed。 91 func (mux *TypeMux) Post(ev interface{}) error { 92 event := &TypeMuxEvent{ 93 Time: time.Now(), 94 Data: ev, 95 } 96 rtyp := reflect.TypeOf(ev) 97 mux.mutex.RLock() 98 if mux.stopped { 99 mux.mutex.RUnlock() 100 return ErrMuxClosed 101 } 102 subs := mux.subm[rtyp] 103 mux.mutex.RUnlock() 104 for _, sub := range subs { 105 sub.deliver(event) 106 } 107 return nil 108 } 109 110 //停止关闭一个多路复用器。MUX不能再使用了。 111 //以后的Post调用将失败,并关闭errmuxClose。 112 //停止块,直到所有当前交货完成。 113 func (mux *TypeMux) Stop() { 114 mux.mutex.Lock() 115 for _, subs := range mux.subm { 116 for _, sub := range subs { 117 sub.closewait() 118 } 119 } 120 mux.subm = nil 121 mux.stopped = true 122 mux.mutex.Unlock() 123 } 124 125 func (mux *TypeMux) del(s *TypeMuxSubscription) { 126 mux.mutex.Lock() 127 for typ, subs := range mux.subm { 128 if pos := find(subs, s); pos >= 0 { 129 if len(subs) == 1 { 130 delete(mux.subm, typ) 131 } else { 132 mux.subm[typ] = posdelete(subs, pos) 133 } 134 } 135 } 136 s.mux.mutex.Unlock() 137 } 138 139 func find(slice []*TypeMuxSubscription, item *TypeMuxSubscription) int { 140 for i, v := range slice { 141 if v == item { 142 return i 143 } 144 } 145 return -1 146 } 147 148 func posdelete(slice []*TypeMuxSubscription, pos int) []*TypeMuxSubscription { 149 news := make([]*TypeMuxSubscription, len(slice)-1) 150 copy(news[:pos], slice[:pos]) 151 copy(news[pos:], slice[pos+1:]) 152 return news 153 } 154 155 //typemux订阅是通过typemux建立的订阅。 156 type TypeMuxSubscription struct { 157 mux *TypeMux 158 created time.Time 159 closeMu sync.Mutex 160 closing chan struct{} 161 closed bool 162 163 //这两个频道是同一频道。它们分开存放,所以 164 //post可以设置为nil,而不影响 165 //陈。 166 postMu sync.RWMutex 167 readC <-chan *TypeMuxEvent 168 postC chan<- *TypeMuxEvent 169 } 170 171 func newsub(mux *TypeMux) *TypeMuxSubscription { 172 c := make(chan *TypeMuxEvent) 173 return &TypeMuxSubscription{ 174 mux: mux, 175 created: time.Now(), 176 readC: c, 177 postC: c, 178 closing: make(chan struct{}), 179 } 180 } 181 182 func (s *TypeMuxSubscription) Chan() <-chan *TypeMuxEvent { 183 return s.readC 184 } 185 186 func (s *TypeMuxSubscription) Unsubscribe() { 187 s.mux.del(s) 188 s.closewait() 189 } 190 191 func (s *TypeMuxSubscription) Closed() bool { 192 s.closeMu.Lock() 193 defer s.closeMu.Unlock() 194 return s.closed 195 } 196 197 func (s *TypeMuxSubscription) closewait() { 198 s.closeMu.Lock() 199 defer s.closeMu.Unlock() 200 if s.closed { 201 return 202 } 203 close(s.closing) 204 s.closed = true 205 206 s.postMu.Lock() 207 close(s.postC) 208 s.postC = nil 209 s.postMu.Unlock() 210 } 211 212 func (s *TypeMuxSubscription) deliver(event *TypeMuxEvent) { 213 //失效事件时短路交付 214 if s.created.After(event.Time) { 215 return 216 } 217 //否则,交付活动 218 s.postMu.RLock() 219 defer s.postMu.RUnlock() 220 221 select { 222 case s.postC <- event: 223 case <-s.closing: 224 } 225 }