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