github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/common/mclock/simclock.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  //版权所有2018 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  package mclock
    26  
    27  import (
    28  	"sync"
    29  	"time"
    30  )
    31  
    32  //
    33  //在实际处理占用零时间的虚拟时间刻度上模拟调度程序。
    34  //
    35  //虚拟时钟本身不前进,调用run前进并执行计时器。
    36  //由于无法影响Go调度程序,因此测试涉及的超时行为
    37  //戈罗蒂内斯需要特别照顾。测试这种超时的一个好方法是:首先
    38  //执行应该超时的操作。确保要测试的计时器
    39  //创建。然后运行时钟直到超时之后。最后观察
    40  //使用通道或信号量的超时。
    41  type Simulated struct {
    42  	now       AbsTime
    43  	scheduled []event
    44  	mu        sync.RWMutex
    45  	cond      *sync.Cond
    46  }
    47  
    48  type event struct {
    49  	do func()
    50  	at AbsTime
    51  }
    52  
    53  //RUN按给定的持续时间移动时钟,在该持续时间之前执行所有计时器。
    54  func (s *Simulated) Run(d time.Duration) {
    55  	s.mu.Lock()
    56  	defer s.mu.Unlock()
    57  	s.init()
    58  
    59  	end := s.now + AbsTime(d)
    60  	for len(s.scheduled) > 0 {
    61  		ev := s.scheduled[0]
    62  		if ev.at > end {
    63  			break
    64  		}
    65  		s.now = ev.at
    66  		ev.do()
    67  		s.scheduled = s.scheduled[1:]
    68  	}
    69  	s.now = end
    70  }
    71  
    72  func (s *Simulated) ActiveTimers() int {
    73  	s.mu.RLock()
    74  	defer s.mu.RUnlock()
    75  
    76  	return len(s.scheduled)
    77  }
    78  
    79  func (s *Simulated) WaitForTimers(n int) {
    80  	s.mu.Lock()
    81  	defer s.mu.Unlock()
    82  	s.init()
    83  
    84  	for len(s.scheduled) < n {
    85  		s.cond.Wait()
    86  	}
    87  }
    88  
    89  //现在实现时钟。
    90  func (s *Simulated) Now() AbsTime {
    91  	s.mu.RLock()
    92  	defer s.mu.RUnlock()
    93  
    94  	return s.now
    95  }
    96  
    97  //睡眠实现时钟。
    98  func (s *Simulated) Sleep(d time.Duration) {
    99  	<-s.After(d)
   100  }
   101  
   102  //在执行时钟之后。
   103  func (s *Simulated) After(d time.Duration) <-chan time.Time {
   104  	after := make(chan time.Time, 1)
   105  	s.insert(d, func() {
   106  		after <- (time.Time{}).Add(time.Duration(s.now))
   107  	})
   108  	return after
   109  }
   110  
   111  func (s *Simulated) insert(d time.Duration, do func()) {
   112  	s.mu.Lock()
   113  	defer s.mu.Unlock()
   114  	s.init()
   115  
   116  	at := s.now + AbsTime(d)
   117  	l, h := 0, len(s.scheduled)
   118  	ll := h
   119  	for l != h {
   120  		m := (l + h) / 2
   121  		if at < s.scheduled[m].at {
   122  			h = m
   123  		} else {
   124  			l = m + 1
   125  		}
   126  	}
   127  	s.scheduled = append(s.scheduled, event{})
   128  	copy(s.scheduled[l+1:], s.scheduled[l:ll])
   129  	s.scheduled[l] = event{do: do, at: at}
   130  	s.cond.Broadcast()
   131  }
   132  
   133  func (s *Simulated) init() {
   134  	if s.cond == nil {
   135  		s.cond = sync.NewCond(&s.mu)
   136  	}
   137  }