mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
refactor: simplify select to exclude task handling
This commit is contained in:
parent
ed463c1ba2
commit
86da86c4ac
1 changed files with 81 additions and 97 deletions
|
|
@ -18,6 +18,7 @@ package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
@ -367,29 +368,29 @@ func (sf *subfetcher) loop() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var tasks []*subfetcherTask
|
work := make(chan *subfetcherTask)
|
||||||
// Adding a default case to the select statement would spin the for loop so
|
go func() {
|
||||||
// we instead have a `work` channel signaller. A necessary invariant is that
|
var wg sync.WaitGroup
|
||||||
// there is a buffered item i.f.f. there are tasks; therefore only
|
|
||||||
// addTasks() may append to the above slice and only the <-work branch may
|
|
||||||
// deplete it.
|
|
||||||
work := make(chan struct{}, 1)
|
|
||||||
defer close(work)
|
|
||||||
addTasks := func(ts []*subfetcherTask) {
|
|
||||||
tasks = append(tasks, ts...)
|
|
||||||
select {
|
|
||||||
case work <- struct{}{}:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ts := <-sf.tasks:
|
case tasks := <-sf.tasks:
|
||||||
addTasks(ts)
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for _, t := range tasks {
|
||||||
|
work <- t
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
case <-work:
|
case <-sf.stop:
|
||||||
for _, task := range tasks {
|
wg.Wait() // guarantee of no more sends on `work`
|
||||||
|
close(work)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for task := range work {
|
||||||
if task.addr != nil {
|
if task.addr != nil {
|
||||||
key := *task.addr
|
key := *task.addr
|
||||||
if task.read {
|
if task.read {
|
||||||
|
|
@ -452,21 +453,4 @@ func (sf *subfetcher) loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tasks = tasks[:0] // avoid reallocation
|
|
||||||
|
|
||||||
case <-sf.stop:
|
|
||||||
// Termination is requested, abort if no more tasks are pending. If
|
|
||||||
// there are some, exhaust them first.
|
|
||||||
if len(tasks) > 0 {
|
|
||||||
// See earlier invariant that guarantees a receive on `work` to clear `tasks`.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case ts := <-sf.tasks:
|
|
||||||
addTasks(ts)
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue