chg(balancer): Comments.
authorsgf <sgf.dma@gmail.com>
Fri, 25 Nov 2022 13:12:10 +0000 (16:12 +0300)
committersgf <sgf.dma@gmail.com>
Fri, 25 Nov 2022 13:12:10 +0000 (16:12 +0300)
concurrency-is-not-parallelism/balancer_v2/balancer/balancer.go

index 7e70326..86ff8f9 100644 (file)
@@ -93,6 +93,20 @@ type Balancer struct {
     done chan *Done
 }
 
+// So, the current communication scheme is following
+//
+//                      ........... Done .............
+//                      v                            |
+//      Generate --> Balance --> [WorkRunner .. x .. x]
+//          ^                                   |
+//          ............ (result) ...............
+//
+// which means, that if 'Generate()' is ever blocks in request sending
+// select's case branch and won't be able to obtain result from WorkRunner,
+// deadlock will happen. If Balance() is ever blocks in sending request to
+// worker and won't be able to get 'Done' message from any other worker,
+// deadlock will happen.
+//
 func (b *Balancer) Balance(work <-chan Requester) {
     fmt.Println("balance(): Starting workers..")
     for _, w := range b.pool {
@@ -126,6 +140,10 @@ out:
 func (b *Balancer) dispatch(req Requester) {
     w := heap.Pop(&b.pool).(*worker)
     w.pending++
+    // I should place worker object back on the heap as soon as i can (or even
+    // use mutex for this), so if i'll block at Send() below, completed() can
+    // run for this worker (otherwise, completed() won't find worker in the
+    // heap and panic).
     heap.Push(&b.pool, w)
     fmt.Printf("dispatch() '%v': sending to '%v'\n", req, w)
     w.runner.Send(req)