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