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  }