github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2012/waza/load2 (about) 1 type Request struct { 2 fn func() int // The operation to perform. 3 c chan int // The channel to return the result. 4 } 5 6 func requester(work chan<- Request) { 7 c := make(chan int) 8 for { 9 // Kill some time (fake load). 10 Sleep(rand.Int63n(nWorker * 2 * Second)) 11 work <- Request{workFn, c} // send request 12 result := <-c // wait for answer 13 furtherProcess(result) 14 } 15 } 16 17 func (w *Worker) work(done chan *Worker) { 18 for { 19 req := <-w.requests // get Request from balancer 20 req.c <- req.fn() // call fn and send result 21 done <- w // we've finished this request 22 } 23 } 24 25 type Pool []*Worker 26 27 type Balancer struct { 28 pool Pool 29 done chan *Worker 30 } 31 32 func (b *Balancer) balance(work chan Request) { 33 for { 34 select { 35 case req := <-work: // received a Request... 36 b.dispatch(req) // ...so send it to a Worker 37 case w := <-b.done: // a worker has finished ... 38 b.completed(w) // ...so update its info 39 } 40 } 41 } 42 func (p Pool) Less(i, j int) bool { 43 return p[i].pending < p[j].pending 44 } 45 46 type Worker struct { 47 requests chan Request // work to do (buffered channel) 48 pending int // count of pending tasks 49 index int // index in the heap 50 } 51 52 // Send Request to worker 53 func (b *Balancer) dispatch(req Request) { 54 // Grab the least loaded worker... 55 w := heap.Pop(&b.pool).(*Worker) 56 // ...send it the task. 57 w.requests <- req 58 // One more in its work queue. 59 w.pending++ 60 // Put it into its place on the heap. 61 heap.Push(&b.pool, w) 62 } 63 64 // Job is complete; update heap 65 func (b *Balancer) completed(w *Worker) { 66 // One fewer in the queue. 67 w.pending-- 68 // Remove it from heap. 69 heap.Remove(&b.pool, w.index) 70 // Put it into its place on the heap. 71 heap.Push(&b.pool, w) 72 } 73 74 func (p Pool) Less(i, j int) bool { 75 return p[i].pending < p[j].pending 76 }