github.com/sercand/please@v13.4.0+incompatible/src/run/pool.go (about)

     1  package run
     2  
     3  // A GoroutinePool manages a set of worker goroutines, analogous to a traditional threadpool.
     4  // Obviously in classic Go you do not need one, but this can be useful when you have external
     5  // resources being driven by it that can't scale like goroutines (for example processes)
     6  type GoroutinePool struct {
     7  	ch chan func()
     8  }
     9  
    10  // NewGoroutinePool allocates a new goroutine pool with the given maximum capacity
    11  // (i.e. number of goroutines).
    12  func NewGoroutinePool(capacity int) *GoroutinePool {
    13  	// Buffer to a reasonably large capacity to try to prevent too much blocking on Submit().
    14  	ch := make(chan func(), capacity*10)
    15  	for i := 0; i < capacity; i++ {
    16  		go runWorker(ch)
    17  	}
    18  	return &GoroutinePool{
    19  		ch: ch,
    20  	}
    21  }
    22  
    23  // Submit submits a new work unit to the pool. It will be handled once a worker is free.
    24  // Note that we only accept a niladic function, and do not provide an indication of when it
    25  // completes, so you would typically wrap the call you want in an anonymous function, i.e.
    26  //   var wg sync.WaitGroup
    27  //   wg.Add(1)
    28  //   pool.Submit(func() {
    29  //       callMyRealFunction(someParam)
    30  //       wg.Done()
    31  //   })
    32  //   wg.Wait()
    33  //
    34  // Hint: ensure you are careful about closing over loop variables, Go closes over them by
    35  //       reference not value so you may need to wrap them again (or use SubmitParam instead).
    36  //
    37  // No particular guarantee is made about whether this function will block or not.
    38  func (pool *GoroutinePool) Submit(f func()) {
    39  	pool.ch <- f
    40  }
    41  
    42  // SubmitParam is similar to Submit but allows submitting a single parameter with the function.
    43  // This is often convenient to close over loop variables etc.
    44  func (pool *GoroutinePool) SubmitParam(f func(interface{}), p interface{}) {
    45  	pool.ch <- func() {
    46  		f(p)
    47  	}
    48  }
    49  
    50  // runWorker is the body of the actual worker.
    51  func runWorker(ch <-chan func()) {
    52  	for {
    53  		f := <-ch
    54  		f()
    55  	}
    56  }