github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/network/priorityqueue/priorityqueue.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  //包优先级队列实现基于通道的优先级队列
    26  //在任意类型上。它提供了一个
    27  //一个自动操作循环,将一个函数应用于始终遵守的项
    28  //他们的优先权。结构只是准一致的,即如果
    29  //优先项是自动停止的,保证有一点
    30  //当没有更高优先级的项目时,即不能保证
    31  //有一点低优先级的项目存在
    32  //但更高的不是
    33  
    34  package priorityqueue
    35  
    36  import (
    37  	"context"
    38  	"errors"
    39  )
    40  
    41  var (
    42  	errContention  = errors.New("queue contention")
    43  	errBadPriority = errors.New("bad priority")
    44  
    45  	wakey = struct{}{}
    46  )
    47  
    48  //PriorityQueue是基本结构
    49  type PriorityQueue struct {
    50  	queues []chan interface{}
    51  	wakeup chan struct{}
    52  }
    53  
    54  //New是PriorityQueue的构造函数
    55  func New(n int, l int) *PriorityQueue {
    56  	var queues = make([]chan interface{}, n)
    57  	for i := range queues {
    58  		queues[i] = make(chan interface{}, l)
    59  	}
    60  	return &PriorityQueue{
    61  		queues: queues,
    62  		wakeup: make(chan struct{}, 1),
    63  	}
    64  }
    65  
    66  //运行是从队列中弹出项目的永久循环
    67  func (pq *PriorityQueue) Run(ctx context.Context, f func(interface{})) {
    68  	top := len(pq.queues) - 1
    69  	p := top
    70  READ:
    71  	for {
    72  		q := pq.queues[p]
    73  		select {
    74  		case <-ctx.Done():
    75  			return
    76  		case x := <-q:
    77  			f(x)
    78  			p = top
    79  		default:
    80  			if p > 0 {
    81  				p--
    82  				continue READ
    83  			}
    84  			p = top
    85  			select {
    86  			case <-ctx.Done():
    87  				return
    88  			case <-pq.wakeup:
    89  			}
    90  		}
    91  	}
    92  }
    93  
    94  //push将项目推送到priority参数中指定的适当队列
    95  //如果给定了上下文,它将一直等到推送该项或上下文中止为止。
    96  //否则,如果队列已满,则返回errCompetition
    97  func (pq *PriorityQueue) Push(ctx context.Context, x interface{}, p int) error {
    98  	if p < 0 || p >= len(pq.queues) {
    99  		return errBadPriority
   100  	}
   101  	if ctx == nil {
   102  		select {
   103  		case pq.queues[p] <- x:
   104  		default:
   105  			return errContention
   106  		}
   107  	} else {
   108  		select {
   109  		case pq.queues[p] <- x:
   110  		case <-ctx.Done():
   111  			return ctx.Err()
   112  		}
   113  	}
   114  	select {
   115  	case pq.wakeup <- wakey:
   116  	default:
   117  	}
   118  	return nil
   119  }