gomod2nix/lib/executor.go
adisbladis e1d46e6973 Reintroduce the max workers flag
It turns out that this is actually useful to limit the number of open files.

Fixes https://github.com/tweag/gomod2nix/issues/50.
2022-05-31 02:07:27 +08:00

75 lines
1.1 KiB
Go

package lib
import (
"sync"
)
// ParallellExecutor - Execute callback functions in parallell
type ParallellExecutor struct {
errChan chan error
wg *sync.WaitGroup
mux *sync.Mutex
guard chan struct{}
// Error returned by Wait(), cached for other Wait() invocations
err error
done bool
}
func NewParallellExecutor(maxWorkers int) *ParallellExecutor {
return &ParallellExecutor{
errChan: make(chan error),
mux: new(sync.Mutex),
wg: new(sync.WaitGroup),
guard: make(chan struct{}, maxWorkers),
err: nil,
done: false,
}
}
func (e *ParallellExecutor) Add(fn func() error) {
e.wg.Add(1)
e.guard <- struct{}{} // Block until a worker is available
go func() {
defer e.wg.Done()
defer func() {
<-e.guard
}()
err := fn()
if err != nil {
e.errChan <- err
}
}()
}
func (e *ParallellExecutor) Wait() error {
e.mux.Lock()
defer e.mux.Unlock()
if e.done {
return e.err
}
var err error
// Ensure channel is closed
go func() {
e.wg.Wait()
close(e.errChan)
}()
for err = range e.errChan {
if err != nil {
break
}
}
e.done = true
e.err = err
return err
}