github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/execqueue.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:38</date>
    10  //</624450093465997312>
    11  
    12  
    13  package les
    14  
    15  import "sync"
    16  
    17  //execqueue实现在单个线程中执行函数调用的队列,
    18  //与排队的顺序相同。
    19  type execQueue struct {
    20  	mu        sync.Mutex
    21  	cond      *sync.Cond
    22  	funcs     []func()
    23  	closeWait chan struct{}
    24  }
    25  
    26  //NeXeExcel队列创建一个新的执行队列。
    27  func newExecQueue(capacity int) *execQueue {
    28  	q := &execQueue{funcs: make([]func(), 0, capacity)}
    29  	q.cond = sync.NewCond(&q.mu)
    30  	go q.loop()
    31  	return q
    32  }
    33  
    34  func (q *execQueue) loop() {
    35  	for f := q.waitNext(false); f != nil; f = q.waitNext(true) {
    36  		f()
    37  	}
    38  	close(q.closeWait)
    39  }
    40  
    41  func (q *execQueue) waitNext(drop bool) (f func()) {
    42  	q.mu.Lock()
    43  	if drop {
    44  //删除刚刚执行的函数。我们在这里而不是在什么时候
    45  //出列so len(q.funcs)包括正在运行的函数。
    46  		q.funcs = append(q.funcs[:0], q.funcs[1:]...)
    47  	}
    48  	for !q.isClosed() {
    49  		if len(q.funcs) > 0 {
    50  			f = q.funcs[0]
    51  			break
    52  		}
    53  		q.cond.Wait()
    54  	}
    55  	q.mu.Unlock()
    56  	return f
    57  }
    58  
    59  func (q *execQueue) isClosed() bool {
    60  	return q.closeWait != nil
    61  }
    62  
    63  //如果可以向执行队列中添加更多函数调用,则can queue返回true。
    64  func (q *execQueue) canQueue() bool {
    65  	q.mu.Lock()
    66  	ok := !q.isClosed() && len(q.funcs) < cap(q.funcs)
    67  	q.mu.Unlock()
    68  	return ok
    69  }
    70  
    71  //queue向执行队列添加函数调用。如果成功,则返回true。
    72  func (q *execQueue) queue(f func()) bool {
    73  	q.mu.Lock()
    74  	ok := !q.isClosed() && len(q.funcs) < cap(q.funcs)
    75  	if ok {
    76  		q.funcs = append(q.funcs, f)
    77  		q.cond.Signal()
    78  	}
    79  	q.mu.Unlock()
    80  	return ok
    81  }
    82  
    83  //quit停止执行队列。
    84  //quit在返回之前等待当前执行完成。
    85  func (q *execQueue) quit() {
    86  	q.mu.Lock()
    87  	if !q.isClosed() {
    88  		q.closeWait = make(chan struct{})
    89  		q.cond.Signal()
    90  	}
    91  	q.mu.Unlock()
    92  	<-q.closeWait
    93  }
    94