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