]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/par: generic Work
authorRoger Peppe <rogpeppe@gmail.com>
Mon, 30 Jan 2023 17:24:14 +0000 (17:24 +0000)
committerroger peppe <rogpeppe@gmail.com>
Wed, 1 Feb 2023 20:28:59 +0000 (20:28 +0000)
This makes the mvs code slightly clearer.

Change-Id: Idefc36bd1066f0348a70e7c91c37a0d56f3c02d5
Reviewed-on: https://go-review.googlesource.com/c/go/+/463844
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: roger peppe <rogpeppe@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
src/cmd/go/internal/mvs/mvs.go
src/cmd/go/internal/par/work.go
src/cmd/go/internal/par/work_test.go

index eb33ebd24b9457b8ef785d19388302be743cafd3..ec5e49a1a6a5b612e7e89b1e342957eb21d89adc 100644 (file)
@@ -110,12 +110,11 @@ func buildList(targets []module.Version, reqs Reqs, upgrade func(module.Version)
 
        // Explore work graph in parallel in case reqs.Required
        // does high-latency network operations.
-       var work par.Work
+       var work par.Work[module.Version]
        for _, target := range targets {
                work.Add(target)
        }
-       work.Do(10, func(item any) {
-               m := item.(module.Version)
+       work.Do(10, func(m module.Version) {
 
                var required []module.Version
                var err error
index 7626251087bd50bdf0cf26c3a9af0fa7d3bc5da1..8912a3aa7dc423d162c9a84a16b1ddc8288e65c4 100644 (file)
@@ -13,25 +13,25 @@ import (
 
 // Work manages a set of work items to be executed in parallel, at most once each.
 // The items in the set must all be valid map keys.
-type Work struct {
-       f       func(any) // function to run for each item
-       running int       // total number of runners
+type Work[T comparable] struct {
+       f       func(T) // function to run for each item
+       running int     // total number of runners
 
        mu      sync.Mutex
-       added   map[any]bool // items added to set
-       todo    []any        // items yet to be run
-       wait    sync.Cond    // wait when todo is empty
-       waiting int          // number of runners waiting for todo
+       added   map[T]bool // items added to set
+       todo    []T        // items yet to be run
+       wait    sync.Cond  // wait when todo is empty
+       waiting int        // number of runners waiting for todo
 }
 
-func (w *Work) init() {
+func (w *Work[T]) init() {
        if w.added == nil {
-               w.added = make(map[any]bool)
+               w.added = make(map[T]bool)
        }
 }
 
 // Add adds item to the work set, if it hasn't already been added.
-func (w *Work) Add(item any) {
+func (w *Work[T]) Add(item T) {
        w.mu.Lock()
        w.init()
        if !w.added[item] {
@@ -51,7 +51,7 @@ func (w *Work) Add(item any) {
 // before calling Do (or else Do returns immediately),
 // but it is allowed for f(item) to add new items to the set.
 // Do should only be used once on a given Work.
-func (w *Work) Do(n int, f func(item any)) {
+func (w *Work[T]) Do(n int, f func(item T)) {
        if n < 1 {
                panic("par.Work.Do: n < 1")
        }
@@ -72,7 +72,7 @@ func (w *Work) Do(n int, f func(item any)) {
 // runner executes work in w until both nothing is left to do
 // and all the runners are waiting for work.
 // (Then all the runners return.)
-func (w *Work) runner() {
+func (w *Work[T]) runner() {
        for {
                // Wait for something to do.
                w.mu.Lock()
index add0e640d8c093423e16c1a3fae1cd2b208bd137..4283e0d08a63f06378a1761ad526ae3df06155fe 100644 (file)
@@ -11,14 +11,13 @@ import (
 )
 
 func TestWork(t *testing.T) {
-       var w Work
+       var w Work[int]
 
        const N = 10000
        n := int32(0)
        w.Add(N)
-       w.Do(100, func(x any) {
+       w.Do(100, func(i int) {
                atomic.AddInt32(&n, 1)
-               i := x.(int)
                if i >= 2 {
                        w.Add(i - 1)
                        w.Add(i - 2)
@@ -33,14 +32,14 @@ func TestWork(t *testing.T) {
 
 func TestWorkParallel(t *testing.T) {
        for tries := 0; tries < 10; tries++ {
-               var w Work
+               var w Work[int]
                const N = 100
                for i := 0; i < N; i++ {
                        w.Add(i)
                }
                start := time.Now()
                var n int32
-               w.Do(N, func(x any) {
+               w.Do(N, func(x int) {
                        time.Sleep(1 * time.Millisecond)
                        atomic.AddInt32(&n, +1)
                })