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  }