Решение на Concurrent Retry Executor от Валентин Латунов

Обратно към всички решения

Към профила на Валентин Латунов

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 9 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
result := make(chan struct {
index int
result string
})
go func() {
waitStart := make(chan struct{}, concurrentLimit)
waitEnd := make(chan struct{})
for index, value := range tasks {
waitStart <- struct{}{}
go func(index int, fnc func() string) {
for i := 0; i < retryLimit; i++ {
res := fnc()
result <- struct {
index int
result string
}{index, res}
if res != "" {
break
}
}
<-waitStart
waitEnd <- struct{}{}
}(index, value)
}
for range tasks {
<-waitEnd
}
close(result)
}()
return result
}

Лог от изпълнението

PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.003s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.030s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.031s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.003s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.003s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.100s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.319s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.683s
PASS
ok  	_/tmp/d20161115-21147-163jo8e	0.203s

История (2 версии и 1 коментар)

Валентин обнови решението на 12.11.2016 19:22 (преди над 1 година)

+package main
+
+import (
+ "sync"
+)
+
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
+ index int
+ result string
+} {
+ result := make(chan struct {
+ index int
+ result string
+ })
+ go func() {
+ done := make(chan struct{}, concurrentLimit)
+ var wg sync.WaitGroup
+ for index, value := range tasks {
+ done <- struct{}{}
+ wg.Add(1)
+ go func(index int, fnc func() string) {
+ for i := 0; i < retryLimit; i++ {
+ res := fnc()
+ result <- struct {
+ index int
+ result string
+ }{index, res}
+ if res != "" {
+ break
+ }
+ }
+ <-done
+ wg.Done()
+ }(index, value)
+ }
+ wg.Wait()
+ close(result)
+ }()
+ return result
+}

Не сме преподавали sync.WaitGroup и понеже задачата е напълно решима без тях, само със материала преподаван до сега бих предпочел ако напишеш решение без тях. Иначе решението ти е вярно и нямам забележки освен горната.

Валентин обнови решението на 13.11.2016 22:43 (преди над 1 година)

package main
-import (
- "sync"
-)
-
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
result := make(chan struct {
index int
result string
})
go func() {
- done := make(chan struct{}, concurrentLimit)
- var wg sync.WaitGroup
+ waitStart := make(chan struct{}, concurrentLimit)
+ waitEnd := make(chan struct{})
for index, value := range tasks {
- done <- struct{}{}
- wg.Add(1)
+ waitStart <- struct{}{}
go func(index int, fnc func() string) {
for i := 0; i < retryLimit; i++ {
res := fnc()
result <- struct {
index int
result string
}{index, res}
if res != "" {
break
}
}
- <-done
- wg.Done()
+ <-waitStart
+ waitEnd <- struct{}{}
+
}(index, value)
}
- wg.Wait()
+ for range tasks {
+ <-waitEnd
+ }
close(result)
}()
return result
}