github.com/AbhinandanKurakure/podman/v3@v3.4.10/pkg/parallel/parallel.go (about)

     1  package parallel
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/sirupsen/logrus"
     9  	"golang.org/x/sync/semaphore"
    10  )
    11  
    12  var (
    13  	// Maximum number of jobs that will be used.
    14  	// Set a low, but non-zero, default. We'll be overriding it by default
    15  	// anyways.
    16  	numThreads uint = 8
    17  	// Semaphore to control thread creation and ensure numThreads is
    18  	// respected.
    19  	jobControl *semaphore.Weighted
    20  	// Lock to control changing the semaphore - we don't want to do it
    21  	// while anyone is using it.
    22  	jobControlLock sync.RWMutex
    23  )
    24  
    25  // SetMaxThreads sets the number of threads that will be used for parallel jobs.
    26  func SetMaxThreads(threads uint) error {
    27  	if threads == 0 {
    28  		return errors.New("must give a non-zero number of threads to execute with")
    29  	}
    30  
    31  	jobControlLock.Lock()
    32  	defer jobControlLock.Unlock()
    33  
    34  	numThreads = threads
    35  	jobControl = semaphore.NewWeighted(int64(threads))
    36  	logrus.Infof("Setting parallel job count to %d", threads)
    37  
    38  	return nil
    39  }
    40  
    41  // GetMaxThreads returns the current number of threads that will be used for
    42  // parallel jobs.
    43  func GetMaxThreads() uint {
    44  	return numThreads
    45  }
    46  
    47  // Enqueue adds a single function to the parallel jobs queue. This function will
    48  // be run when an unused thread is available.
    49  // Returns a receive-only error channel that will return the error (if any) from
    50  // the provided function fn when fn has finished executing. The channel will be
    51  // closed after this.
    52  func Enqueue(ctx context.Context, fn func() error) <-chan error {
    53  	retChan := make(chan error)
    54  
    55  	go func() {
    56  		jobControlLock.RLock()
    57  		defer jobControlLock.RUnlock()
    58  
    59  		defer close(retChan)
    60  
    61  		if err := jobControl.Acquire(ctx, 1); err != nil {
    62  			retChan <- errors.Wrapf(err, "error acquiring job control semaphore")
    63  			return
    64  		}
    65  
    66  		err := fn()
    67  
    68  		jobControl.Release(1)
    69  
    70  		retChan <- err
    71  	}()
    72  
    73  	return retChan
    74  }