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 }