github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/legacy/terraform/util.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package terraform 5 6 import ( 7 "sort" 8 ) 9 10 // Semaphore is a wrapper around a channel to provide 11 // utility methods to clarify that we are treating the 12 // channel as a semaphore 13 type Semaphore chan struct{} 14 15 // NewSemaphore creates a semaphore that allows up 16 // to a given limit of simultaneous acquisitions 17 func NewSemaphore(n int) Semaphore { 18 if n <= 0 { 19 panic("semaphore with limit <=0") 20 } 21 ch := make(chan struct{}, n) 22 return Semaphore(ch) 23 } 24 25 // Acquire is used to acquire an available slot. 26 // Blocks until available. 27 func (s Semaphore) Acquire() { 28 s <- struct{}{} 29 } 30 31 // TryAcquire is used to do a non-blocking acquire. 32 // Returns a bool indicating success 33 func (s Semaphore) TryAcquire() bool { 34 select { 35 case s <- struct{}{}: 36 return true 37 default: 38 return false 39 } 40 } 41 42 // Release is used to return a slot. Acquire must 43 // be called as a pre-condition. 44 func (s Semaphore) Release() { 45 select { 46 case <-s: 47 default: 48 panic("release without an acquire") 49 } 50 } 51 52 // strSliceContains checks if a given string is contained in a slice 53 // When anybody asks why Go needs generics, here you go. 54 func strSliceContains(haystack []string, needle string) bool { 55 for _, s := range haystack { 56 if s == needle { 57 return true 58 } 59 } 60 return false 61 } 62 63 // deduplicate a slice of strings 64 func uniqueStrings(s []string) []string { 65 if len(s) < 2 { 66 return s 67 } 68 69 sort.Strings(s) 70 result := make([]string, 1, len(s)) 71 result[0] = s[0] 72 for i := 1; i < len(s); i++ { 73 if s[i] != result[len(result)-1] { 74 result = append(result, s[i]) 75 } 76 } 77 return result 78 }