github.com/opentofu/opentofu@v1.7.1/internal/legacy/tofu/util.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package tofu
     7  
     8  import (
     9  	"sort"
    10  )
    11  
    12  // Semaphore is a wrapper around a channel to provide
    13  // utility methods to clarify that we are treating the
    14  // channel as a semaphore
    15  type Semaphore chan struct{}
    16  
    17  // NewSemaphore creates a semaphore that allows up
    18  // to a given limit of simultaneous acquisitions
    19  func NewSemaphore(n int) Semaphore {
    20  	if n <= 0 {
    21  		panic("semaphore with limit <=0")
    22  	}
    23  	ch := make(chan struct{}, n)
    24  	return Semaphore(ch)
    25  }
    26  
    27  // Acquire is used to acquire an available slot.
    28  // Blocks until available.
    29  func (s Semaphore) Acquire() {
    30  	s <- struct{}{}
    31  }
    32  
    33  // TryAcquire is used to do a non-blocking acquire.
    34  // Returns a bool indicating success
    35  func (s Semaphore) TryAcquire() bool {
    36  	select {
    37  	case s <- struct{}{}:
    38  		return true
    39  	default:
    40  		return false
    41  	}
    42  }
    43  
    44  // Release is used to return a slot. Acquire must
    45  // be called as a pre-condition.
    46  func (s Semaphore) Release() {
    47  	select {
    48  	case <-s:
    49  	default:
    50  		panic("release without an acquire")
    51  	}
    52  }
    53  
    54  // deduplicate a slice of strings
    55  func uniqueStrings(s []string) []string {
    56  	if len(s) < 2 {
    57  		return s
    58  	}
    59  
    60  	sort.Strings(s)
    61  	result := make([]string, 1, len(s))
    62  	result[0] = s[0]
    63  	for i := 1; i < len(s); i++ {
    64  		if s[i] != result[len(result)-1] {
    65  			result = append(result, s[i])
    66  		}
    67  	}
    68  	return result
    69  }