Решение на Concurrent Retry Executor от Михаил Здравков

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

Към профила на Михаил Здравков

Резултати

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

Код

package main
import "fmt"
func SingleLogDrainer(log, input chan string, last, next, closed chan struct{}, number int) {
buffer := make([]string, 0)
inTurn := false
for {
msg, ok := <-log
if ok {
buffer = append(buffer, msg)
} else if inTurn {
break
}
select {
case <-last:
inTurn = true
default:
}
if inTurn {
for _, msg := range buffer {
input <- fmt.Sprintf("%d\t%s", number, msg)
buffer = make([]string, 0, 100)
}
}
}
next <- struct{}{}
closed <- struct{}{}
}
func OrderedLogDrainer(logs chan (chan string)) chan string {
result := make(chan string)
input := make(chan string, 100)
syncSender := make(chan struct{})
go func() {
for {
select {
case <-syncSender:
return
case msg := <-input:
result <- msg
}
}
}()
go func() {
logsCount, closedCount := 0, 0
closed := make(chan struct{})
next := make(chan struct{}, 1)
next <- struct{}{}
for {
last := next
next = make(chan struct{}, 1)
if log, ok := <-logs; ok {
logsCount += 1
go SingleLogDrainer(log, input, last, next, closed, logsCount)
} else if closedCount == logsCount && len(input) == 0 {
syncSender <- struct{}{}
close(result)
return
}
select {
case <-closed:
closedCount += 1
default:
}
}
}()
return result
}

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

PASS
ok  	_/tmp/d20151110-19113-1v3yxmj	0.003s
PASS
ok  	_/tmp/d20151110-19113-1v3yxmj	0.003s
PASS
ok  	_/tmp/d20151110-19113-1v3yxmj	0.003s
PASS
ok  	_/tmp/d20151110-19113-1v3yxmj	0.003s
PASS
ok  	_/tmp/d20151110-19113-1v3yxmj	0.003s
PASS
ok  	_/tmp/d20151110-19113-1v3yxmj	0.703s
PASS
ok  	_/tmp/d20151110-19113-1v3yxmj	0.005s
--- FAIL: TestWithManyLogs (0.82s)
	solution_test.go:27: Test exceeded allowed time of 800 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1v3yxmj	0.821s

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

Михаил обнови решението на 09.11.2015 01:42 (преди над 2 години)

+package main
+
+import "fmt"
+
+func SingleLogDrainer(log, input chan string, last, next, closed chan struct{}, number int) {
+ buffer := make([]string, 0)
+ inTurn := false
+ for {
+ msg, ok := <-log
+ if ok {
+ buffer = append(buffer, msg)
+ } else if inTurn {
+ break
+ }
+ select {
+ case <-last:
+ inTurn = true
+ default:
+ }
+ if inTurn {
+ for _, msg := range buffer {
+ input <- fmt.Sprintf("%d\t%s", number, msg)
+ buffer = make([]string, 0, 100)
+ }
+ }
+ }
+ next <- struct{}{}
+ closed <- struct{}{}
+}
+
+func OrderedLogDrainer(logs chan (chan string)) chan string {
+ result := make(chan string)
+ input := make(chan string, 100)
+ syncSender := make(chan struct{})
+
+ go func() {
+ for {
+ select {
+ case <-syncSender:
+ return
+ case msg := <-input:
+ result <- msg
+ }
+ }
+ }()
+
+ go func() {
+ logsCount, closedCount := 0, 0
+ closed := make(chan struct{})
+ next := make(chan struct{}, 1)
+ next <- struct{}{}
+ for {
+ last := next
+ next = make(chan struct{}, 1)
+ if log, ok := <-logs; ok {
+ logsCount += 1
+ go SingleLogDrainer(log, input, last, next, closed, logsCount)
+ } else if closedCount == logsCount && len(input) == 0 {
+ syncSender <- struct{}{}
+ close(result)
+ return
+ }
+ select {
+ case <-closed:
+ closedCount += 1
+ default:
+ }
+ }
+ }()
+
+ return result
+}