github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/upload/concurrent/pool.go (about) 1 package concurrent 2 3 import ( 4 "bytes" 5 "fmt" 6 "sync" 7 ) 8 9 // Pool is the collection of Worker, it is a min-heap that implements heap.Interface. 10 // The priority is the number of pending works assigned to the worker. Lower the pending 11 // work count higher the priority. Pool embeds sync.RWMutex to support concurrent heap 12 // operation. 13 // 14 type Pool struct { 15 sync.RWMutex // If consumer want to use workers in a concurrent environment 16 Workers []*Worker // The workers 17 } 18 19 // Len returns number of workers in the pool. 20 // 21 func (p *Pool) Len() int { 22 return len(p.Workers) 23 } 24 25 // Less returns true if priority of Worker instance at index i is less than priority of Worker 26 // instance at j, lower the pending value higher the priority 27 // 28 func (p *Pool) Less(i, j int) bool { 29 return p.Workers[i].Pending < p.Workers[j].Pending 30 } 31 32 // Swap swaps the Worker instances at the given indices i and j 33 // 34 func (p Pool) Swap(i, j int) { 35 p.Workers[i], p.Workers[j] = p.Workers[j], p.Workers[i] 36 p.Workers[i].Index = i 37 p.Workers[j].Index = j 38 } 39 40 // Push is used by heap.Push implementation, to add a worker w to a Pool pool, we call 41 // heap.Push(&pool, w) which invokes this method to add the worker to the end of collection 42 // then it fix the heap by moving the added item to its correct position. 43 // 44 func (p *Pool) Push(x interface{}) { 45 n := len(p.Workers) 46 worker := x.(*Worker) 47 worker.Index = n 48 (*p).Workers = append((*p).Workers, worker) 49 } 50 51 // Pop is used by heap.Pop implementation, to pop a worker w with minimum priority from a Pool 52 // p, we call w := heap.Pop(&p).(*Worker), which swap the min priority worker at the beginning 53 // of the pool with the end of item, fix the heap and then invokes this method for popping the 54 // worker from the end. 55 // 56 func (p *Pool) Pop() interface{} { 57 n := len(p.Workers) 58 w := (*p).Workers[n-1] 59 w.Index = -1 60 (*p).Workers = (*p).Workers[0 : n-1] 61 return w 62 } 63 64 // WorkersCurrentLoad returns the load of the workers as comma separated string values, where 65 // each value consists of worker id (Worker.Id property) and pending requests associated with 66 // the worker. 67 // 68 func (p *Pool) WorkersCurrentLoad() string { 69 var buffer bytes.Buffer 70 buffer.WriteString("Load [") 71 for _, w := range p.Workers { 72 buffer.WriteString(fmt.Sprintf("%d:%d, ", w.ID, w.Pending)) 73 } 74 buffer.WriteString("]") 75 return buffer.String() 76 }