76 lines
1.5 KiB
Go
76 lines
1.5 KiB
Go
package terraform
|
|
|
|
import (
|
|
"sort"
|
|
)
|
|
|
|
// Semaphore is a wrapper around a channel to provide
|
|
// utility methods to clarify that we are treating the
|
|
// channel as a semaphore
|
|
type Semaphore chan struct{}
|
|
|
|
// NewSemaphore creates a semaphore that allows up
|
|
// to a given limit of simultaneous acquisitions
|
|
func NewSemaphore(n int) Semaphore {
|
|
if n <= 0 {
|
|
panic("semaphore with limit <=0")
|
|
}
|
|
ch := make(chan struct{}, n)
|
|
return Semaphore(ch)
|
|
}
|
|
|
|
// Acquire is used to acquire an available slot.
|
|
// Blocks until available.
|
|
func (s Semaphore) Acquire() {
|
|
s <- struct{}{}
|
|
}
|
|
|
|
// TryAcquire is used to do a non-blocking acquire.
|
|
// Returns a bool indicating success
|
|
func (s Semaphore) TryAcquire() bool {
|
|
select {
|
|
case s <- struct{}{}:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Release is used to return a slot. Acquire must
|
|
// be called as a pre-condition.
|
|
func (s Semaphore) Release() {
|
|
select {
|
|
case <-s:
|
|
default:
|
|
panic("release without an acquire")
|
|
}
|
|
}
|
|
|
|
// strSliceContains checks if a given string is contained in a slice
|
|
// When anybody asks why Go needs generics, here you go.
|
|
func strSliceContains(haystack []string, needle string) bool {
|
|
for _, s := range haystack {
|
|
if s == needle {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// deduplicate a slice of strings
|
|
func uniqueStrings(s []string) []string {
|
|
if len(s) < 2 {
|
|
return s
|
|
}
|
|
|
|
sort.Strings(s)
|
|
result := make([]string, 1, len(s))
|
|
result[0] = s[0]
|
|
for i := 1; i < len(s); i++ {
|
|
if s[i] != result[len(result)-1] {
|
|
result = append(result, s[i])
|
|
}
|
|
}
|
|
return result
|
|
}
|