github.com/vmware/govmomi@v0.51.0/vim25/progress/aggregator.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package progress
     6  
     7  import "sync"
     8  
     9  type Aggregator struct {
    10  	downstream Sinker
    11  	upstream   chan (<-chan Report)
    12  
    13  	done chan struct{}
    14  	w    sync.WaitGroup
    15  }
    16  
    17  func NewAggregator(s Sinker) *Aggregator {
    18  	a := &Aggregator{
    19  		downstream: s,
    20  		upstream:   make(chan (<-chan Report)),
    21  
    22  		done: make(chan struct{}),
    23  	}
    24  
    25  	a.w.Add(1)
    26  	go a.loop()
    27  
    28  	return a
    29  }
    30  
    31  func (a *Aggregator) loop() {
    32  	defer a.w.Done()
    33  
    34  	dch := a.downstream.Sink()
    35  	defer close(dch)
    36  
    37  	for {
    38  		select {
    39  		case uch := <-a.upstream:
    40  			// Drain upstream channel
    41  			for e := range uch {
    42  				dch <- e
    43  			}
    44  		case <-a.done:
    45  			return
    46  		}
    47  	}
    48  }
    49  
    50  func (a *Aggregator) Sink() chan<- Report {
    51  	ch := make(chan Report)
    52  	a.upstream <- ch
    53  	return ch
    54  }
    55  
    56  // Done marks the aggregator as done. No more calls to Sink() may be made and
    57  // the downstream progress report channel will be closed when Done() returns.
    58  func (a *Aggregator) Done() {
    59  	close(a.done)
    60  	a.w.Wait()
    61  }