yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/concurrent/pool.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package concurrent 16 17 import ( 18 "bytes" 19 "fmt" 20 "sync" 21 ) 22 23 // Pool is the collection of Worker, it is a min-heap that implements heap.Interface. 24 // The priority is the number of pending works assigned to the worker. Lower the pending 25 // work count higher the priority. Pool embeds sync.RWMutex to support concurrent heap 26 // operation. 27 // 28 type Pool struct { 29 sync.RWMutex // If consumer want to use workers in a concurrent environment 30 Workers []*Worker // The workers 31 } 32 33 // Len returns number of workers in the pool. 34 // 35 func (p *Pool) Len() int { 36 return len(p.Workers) 37 } 38 39 // Less returns true if priority of Worker instance at index i is less than priority of Worker 40 // instance at j, lower the pending value higher the priority 41 // 42 func (p *Pool) Less(i, j int) bool { 43 return p.Workers[i].Pending < p.Workers[j].Pending 44 } 45 46 // Swap swaps the Worker instances at the given indices i and j 47 // 48 func (p *Pool) Swap(i, j int) { 49 p.Workers[i], p.Workers[j] = p.Workers[j], p.Workers[i] 50 p.Workers[i].Index = i 51 p.Workers[j].Index = j 52 } 53 54 // Push is used by heap.Push implementation, to add a worker w to a Pool pool, we call 55 // heap.Push(&pool, w) which invokes this method to add the worker to the end of collection 56 // then it fix the heap by moving the added item to its correct position. 57 // 58 func (p *Pool) Push(x interface{}) { 59 n := len(p.Workers) 60 worker := x.(*Worker) 61 worker.Index = n 62 (*p).Workers = append((*p).Workers, worker) 63 } 64 65 // Pop is used by heap.Pop implementation, to pop a worker w with minimum priority from a Pool 66 // p, we call w := heap.Pop(&p).(*Worker), which swap the min priority worker at the beginning 67 // of the pool with the end of item, fix the heap and then invokes this method for popping the 68 // worker from the end. 69 // 70 func (p *Pool) Pop() interface{} { 71 n := len(p.Workers) 72 w := (*p).Workers[n-1] 73 w.Index = -1 74 (*p).Workers = (*p).Workers[0 : n-1] 75 return w 76 } 77 78 // WorkersCurrentLoad returns the load of the workers as comma separated string values, where 79 // each value consists of worker id (Worker.Id property) and pending requests associated with 80 // the worker. 81 // 82 func (p *Pool) WorkersCurrentLoad() string { 83 var buffer bytes.Buffer 84 buffer.WriteString("Load [") 85 for _, w := range p.Workers { 86 buffer.WriteString(fmt.Sprintf("%d:%d, ", w.ID, w.Pending)) 87 } 88 buffer.WriteString("]") 89 return buffer.String() 90 }