github.com/viant/toolbox@v0.34.5/collections_async.go (about) 1 package toolbox 2 3 import ( 4 "reflect" 5 "sync" 6 ) 7 8 //TrueValueProvider is a function that returns true, it takes one parameters which ignores, 9 //This provider can be used to make map from slice like map[some type]bool 10 11 //ProcessSliceAsync iterates over any slice, it calls handler with each element asynchronously 12 func ProcessSliceAsync(slice interface{}, handler func(item interface{}) bool) { 13 //The common cases with reflection for speed 14 var wg sync.WaitGroup 15 if aSlice, ok := slice.([]interface{}); ok { 16 wg.Add(len(aSlice)) 17 for _, item := range aSlice { 18 go func(item interface{}) { 19 defer wg.Done() 20 handler(item) 21 }(item) 22 23 } 24 wg.Wait() 25 return 26 } 27 if aSlice, ok := slice.([]map[string]interface{}); ok { 28 wg.Add(len(aSlice)) 29 for _, item := range aSlice { 30 go func(item interface{}) { 31 defer wg.Done() 32 handler(item) 33 }(item) 34 35 } 36 wg.Wait() 37 return 38 } 39 //The common cases with reflection for speed 40 if aSlice, ok := slice.([]string); ok { 41 wg.Add(len(aSlice)) 42 for _, item := range aSlice { 43 go func(item interface{}) { 44 defer wg.Done() 45 handler(item) 46 }(item) 47 48 } 49 wg.Wait() 50 return 51 } 52 53 //The common cases with reflection for speed 54 if aSlice, ok := slice.([]int); ok { 55 wg.Add(len(aSlice)) 56 for _, item := range aSlice { 57 go func(item interface{}) { 58 defer wg.Done() 59 handler(item) 60 }(item) 61 } 62 wg.Wait() 63 return 64 } 65 66 sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice) 67 wg.Add(sliceValue.Len()) 68 for i := 0; i < sliceValue.Len(); i++ { 69 go func(item interface{}) { 70 defer wg.Done() 71 handler(item) 72 }(sliceValue.Index(i).Interface()) 73 74 } 75 wg.Wait() 76 } 77 78 //IndexSlice reads passed in slice and applies function that takes a slice item as argument to return a key value. 79 //passed in resulting map needs to match key type return by a key function, and accept slice item type as argument. 80 func IndexSliceAsync(slice, resultingMap, keyFunction interface{}) { 81 var lock = sync.RWMutex{} 82 mapValue := DiscoverValueByKind(resultingMap, reflect.Map) 83 ProcessSliceAsync(slice, func(item interface{}) bool { 84 result := CallFunction(keyFunction, item) 85 lock.Lock() //otherwise, fatal error: concurrent map writes 86 defer lock.Unlock() 87 mapValue.SetMapIndex(reflect.ValueOf(result[0]), reflect.ValueOf(item)) 88 return true 89 }) 90 } 91 92 //SliceToMap reads passed in slice to to apply the key and value function for each item. Result of these calls is placed in the resulting map. 93 func SliceToMapAsync(sourceSlice, targetMap, keyFunction, valueFunction interface{}) { 94 //optimized case 95 var wg sync.WaitGroup 96 var lock = sync.RWMutex{} 97 if stringBoolMap, ok := targetMap.(map[string]bool); ok { 98 if stringSlice, ok := sourceSlice.([]string); ok { 99 if valueFunction, ok := keyFunction.(func(string) bool); ok { 100 if keyFunction, ok := keyFunction.(func(string) string); ok { 101 wg.Add(len(stringSlice)) 102 for _, item := range stringSlice { 103 go func(item string) { 104 defer wg.Done() 105 key := keyFunction(item) 106 value := valueFunction(item) 107 lock.Lock() 108 defer lock.Unlock() 109 stringBoolMap[key] = value 110 }(item) 111 } 112 wg.Wait() 113 return 114 } 115 } 116 } 117 } 118 119 mapValue := DiscoverValueByKind(targetMap, reflect.Map) 120 ProcessSliceAsync(sourceSlice, func(item interface{}) bool { 121 key := CallFunction(keyFunction, item) 122 value := CallFunction(valueFunction, item) 123 lock.Lock() 124 defer lock.Unlock() 125 mapValue.SetMapIndex(reflect.ValueOf(key[0]), reflect.ValueOf(value[0])) 126 return true 127 }) 128 } 129 130 func ProcessSliceWithIndexAsync(slice interface{}, handler func(index int, item interface{}) bool) { 131 var wg sync.WaitGroup 132 if aSlice, ok := slice.([]interface{}); ok { 133 wg.Add(len(aSlice)) 134 for i, item := range aSlice { 135 go func(i int, item interface{}) { 136 defer wg.Done() 137 handler(i, item) 138 }(i, item) 139 } 140 wg.Wait() 141 return 142 } 143 if aSlice, ok := slice.([]string); ok { 144 wg.Add(len(aSlice)) 145 for i, item := range aSlice { 146 go func(i int, item interface{}) { 147 defer wg.Done() 148 handler(i, item) 149 }(i, item) 150 } 151 wg.Wait() 152 return 153 } 154 if aSlice, ok := slice.([]int); ok { 155 wg.Add(len(aSlice)) 156 for i, item := range aSlice { 157 go func(i int, item interface{}) { 158 defer wg.Done() 159 handler(i, item) 160 }(i, item) 161 } 162 wg.Wait() 163 return 164 } 165 166 sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice) 167 wg.Add(sliceValue.Len()) 168 for i := 0; i < sliceValue.Len(); i++ { 169 go func(i int, item interface{}) { 170 defer wg.Done() 171 handler(i, item) 172 }(i, sliceValue.Index(i).Interface()) 173 } 174 wg.Wait() 175 }