Веселин обнови решението на 13.11.2016 16:23 (преди над 1 година)
+package main
+
+func main() {
няма нужда от този main
+
+}
+
+type channelResult struct {
предпочитаме ако не ползвате именувани типове, предвид това че не сме ги преподавали
+ index int
+ result string
+}
+
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan channelResult {
+ ch := make(chan channelResult)
+
+ process := func() {
+ workers := 0
+ tasks_cap := cap(tasks)
+
+ for i := 0; i < tasks_cap; {
+ if workers < concurrentLimit {
+ workers++
+ go executeTask(tasks[i], i, tasks_cap, ch, retryLimit, 1, &workers, false)
+ i++
+ }
+ }
този busy loop не е необходим, има по елегантен начин.
+ }
+
+ go process()
+
+ return ch
+}
+
+func executeTask(f func() string, index int, tasks_cap int, ch chan channelResult, retryLimit int, retries int, workers *int, skip bool) {
+ function_result := f()
+ result := channelResult{index: index, result: function_result}
+
+ ch <- result
+
+ if function_result == "" && retries < retryLimit {
+ executeTask(f, index, tasks_cap, ch, retryLimit, retries+1, workers, true)
защо рекурсия ?
+ } else {
+ *workers--
+
+ if *workers == 0 {
+ close(ch)
+ }
+ }
+}
- всичко което правиш с
workers
е типичен пример за race condition който даже даваме почти директно във лекцията. - част от параметрите в executeTask изглежда само се препращат но не се използват
- busy loop-а трябва да изчезне - както съм писал има елегантен и прост начин преподаден на лекцията с който да не се налага да се върти и да хаби процесорно време
Тук има възможност последните две/три... горутини да минат едновременно когато workers е >1 и после да намалят без да затварят канала.
Този ред може да бъде изпълнен от няколко горутини едновременно със себе си/ ред 22 или 22 ред със себе си от няколко горутини, което би довело до race condition.
Опитай се да измислиш начин на решаване на проблема използваш канали а не int-ове