github.com/pachyderm/pachyderm@v1.13.4/src/client/limit/limit.go (about)

     1  // Package limit provides primitives to limit concurrency.
     2  //
     3  // Note that this is not to be confused with rate-limiting.  With concurrency
     4  // limiting (which is what this package does), you are limiting the number of
     5  // operations that can be running at any given point in time.  With rate
     6  // limiting, you are limiting the number of operations that can be fired
     7  // within a given time window.
     8  //
     9  // For instance, even if you limit concurrency to 1, you can still have N
    10  // requests per second where N is an arbitrarily large number, given that
    11  // each request takes 1/N second to complete.
    12  package limit
    13  
    14  // ConcurrencyLimiter limits the number of concurrent operations
    15  // If the ConcurrencyLimiter is initialized with a concurrency of 0, then
    16  // all of the following functions will be no-ops, meaning that an arbitrary
    17  // concurrency is allowed.
    18  type ConcurrencyLimiter interface {
    19  	// Acquire acquires the right to proceed.  It blocks if the concurrency
    20  	// limit has been reached.
    21  	Acquire()
    22  	// Release signals that an operation has completed.
    23  	Release()
    24  	// Wait blocks until all operations that have called Acquire thus far
    25  	// are completed.
    26  	Wait()
    27  }
    28  
    29  // New returns a new ConcurrencyLimiter with the given limit
    30  func New(concurrency int) ConcurrencyLimiter {
    31  	if concurrency == 0 {
    32  		return &noOpLimiter{}
    33  	}
    34  	return &concurrencyLimiter{make(chan struct{}, concurrency)}
    35  }
    36  
    37  type concurrencyLimiter struct {
    38  	sem chan struct{}
    39  }
    40  
    41  func (c *concurrencyLimiter) Acquire() {
    42  	c.sem <- struct{}{}
    43  }
    44  
    45  func (c *concurrencyLimiter) Release() {
    46  	select {
    47  	case <-c.sem:
    48  	default:
    49  		panic("Release called without matching Acquire")
    50  	}
    51  }
    52  
    53  func (c *concurrencyLimiter) Wait() {
    54  	for i := 0; i < cap(c.sem); i++ {
    55  		c.sem <- struct{}{}
    56  	}
    57  }
    58  
    59  type noOpLimiter struct{}
    60  
    61  func (n *noOpLimiter) Acquire() {}
    62  
    63  func (n *noOpLimiter) Release() {}
    64  
    65  func (n *noOpLimiter) Wait() {}