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