Николай обнови решението на 13.11.2016 20:37 (преди над 1 година)
+// Package main is solution by Nikolay Genov of the second problem
+// in the course for the Go Programming Language in FMI, Sofia University
+package main
+
+type executedTask struct {
+ index int
+ result string
+}
+
+// ConcurrentRetryExecutor executes concurrently up to `concurrentLimit` number of tasks
+// and if a task returns empty string it must retry it until it reaches maximum of
+// `retryLimit` number of total executions.
+// Returns a read only channel of structure with consecutive `index` of the executed tasks
+// and `result` string
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan executedTask {
+ executedTasks := make(chan executedTask)
+ go func() {
+ semaphore := make(chan struct{}, concurrentLimit)
+ defer close(executedTasks)
+ defer close(semaphore)
+ for i := 0; i < concurrentLimit; i++ {
+ semaphore <- struct{}{}
+ defer func() { <-semaphore }()
+ }
+ for index, task := range tasks {
+ index, task := index, task
+ <-semaphore
+ go func() {
+ result := ""
+ for execCount := 1; result == "" && execCount <= retryLimit; execCount++ {
+ result = task()
+ executedTasks <- executedTask{index, result}
+ }
+ semaphore <- struct{}{}
+ }()
+ }
+ }()
+ return executedTasks
+}