Skip to content

Commit

Permalink
refine ForEachIdxErr
Browse files Browse the repository at this point in the history
  • Loading branch information
collateral-damager committed Apr 26, 2024
1 parent 43a82a4 commit 1d996e3
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 21 deletions.
183 changes: 183 additions & 0 deletions coverage.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
mode: atomic
github.com/sourcegraph/conc/waitgroup.go:10.32,12.2 1 1
github.com/sourcegraph/conc/waitgroup.go:28.34,30.12 2 134
github.com/sourcegraph/conc/waitgroup.go:30.12,33.3 2 134
github.com/sourcegraph/conc/waitgroup.go:38.28,43.2 2 6
github.com/sourcegraph/conc/waitgroup.go:47.56,52.2 2 4
github.com/sourcegraph/conc/iter/iter.go:14.33,14.65 1 36
github.com/sourcegraph/conc/iter/iter.go:42.44,42.79 1 4
github.com/sourcegraph/conc/iter/iter.go:53.56,54.43 1 6
github.com/sourcegraph/conc/iter/iter.go:54.43,56.3 1 10034
github.com/sourcegraph/conc/iter/iter.go:61.52,61.90 1 4
github.com/sourcegraph/conc/iter/iter.go:66.67,68.2 1 7
github.com/sourcegraph/conc/iter/iter.go:72.59,74.2 1 6
github.com/sourcegraph/conc/iter/iter.go:78.64,79.29 1 24
github.com/sourcegraph/conc/iter/iter.go:79.29,82.3 1 20
github.com/sourcegraph/conc/iter/iter.go:84.2,85.35 2 24
github.com/sourcegraph/conc/iter/iter.go:85.35,88.3 1 17
github.com/sourcegraph/conc/iter/iter.go:90.2,92.17 2 24
github.com/sourcegraph/conc/iter/iter.go:92.17,94.47 2 123
github.com/sourcegraph/conc/iter/iter.go:94.47,96.4 1 40079
github.com/sourcegraph/conc/iter/iter.go:99.2,100.42 2 24
github.com/sourcegraph/conc/iter/iter.go:100.42,102.3 1 123
github.com/sourcegraph/conc/iter/iter.go:103.2,103.11 1 24
github.com/sourcegraph/conc/iter/iter.go:109.71,110.59 1 21
github.com/sourcegraph/conc/iter/iter.go:110.59,112.3 1 30076
github.com/sourcegraph/conc/iter/iter.go:118.79,119.29 1 43
github.com/sourcegraph/conc/iter/iter.go:119.29,122.3 1 13
github.com/sourcegraph/conc/iter/iter.go:124.2,125.35 2 43
github.com/sourcegraph/conc/iter/iter.go:125.35,128.3 1 33
github.com/sourcegraph/conc/iter/iter.go:130.2,136.17 5 43
github.com/sourcegraph/conc/iter/iter.go:136.17,138.65 2 4177
github.com/sourcegraph/conc/iter/iter.go:138.65,139.42 1 60157
github.com/sourcegraph/conc/iter/iter.go:139.42,140.76 1 32
github.com/sourcegraph/conc/iter/iter.go:140.76,144.6 3 32
github.com/sourcegraph/conc/iter/iter.go:146.5,146.32 1 32
github.com/sourcegraph/conc/iter/iter.go:151.2,152.60 2 43
github.com/sourcegraph/conc/iter/iter.go:152.60,154.3 1 4177
github.com/sourcegraph/conc/iter/iter.go:155.2,157.29 2 43
github.com/sourcegraph/conc/iter/map.go:19.49,21.2 1 6
github.com/sourcegraph/conc/iter/map.go:26.56,28.53 2 7
github.com/sourcegraph/conc/iter/map.go:28.53,30.3 1 20015
github.com/sourcegraph/conc/iter/map.go:31.2,31.12 1 6
github.com/sourcegraph/conc/iter/map.go:39.70,41.2 1 6
github.com/sourcegraph/conc/iter/map.go:47.77,53.53 2 6
github.com/sourcegraph/conc/iter/map.go:53.53,56.17 3 21
github.com/sourcegraph/conc/iter/map.go:56.17,60.4 3 3
github.com/sourcegraph/conc/iter/map.go:62.2,62.34 1 5
github.com/sourcegraph/conc/panics/panics.go:21.33,24.2 2 113
github.com/sourcegraph/conc/panics/panics.go:26.32,27.34 1 113
github.com/sourcegraph/conc/panics/panics.go:27.34,30.3 2 9
github.com/sourcegraph/conc/panics/panics.go:36.29,37.38 1 2
github.com/sourcegraph/conc/panics/panics.go:37.38,38.13 1 1
github.com/sourcegraph/conc/panics/panics.go:44.42,46.2 1 12
github.com/sourcegraph/conc/panics/panics.go:52.50,61.2 3 9
github.com/sourcegraph/conc/panics/panics.go:77.37,79.2 1 6
github.com/sourcegraph/conc/panics/panics.go:83.37,84.14 1 9
github.com/sourcegraph/conc/panics/panics.go:84.14,86.3 1 1
github.com/sourcegraph/conc/panics/panics.go:87.2,87.26 1 8
github.com/sourcegraph/conc/panics/panics.go:95.39,95.60 1 0
github.com/sourcegraph/conc/panics/panics.go:97.39,98.36 1 5
github.com/sourcegraph/conc/panics/panics.go:98.36,100.3 1 3
github.com/sourcegraph/conc/panics/panics.go:101.2,101.12 1 2
github.com/sourcegraph/conc/panics/try.go:7.31,11.2 3 2
github.com/sourcegraph/conc/pool/context_pool.go:24.61,25.30 1 1456
github.com/sourcegraph/conc/pool/context_pool.go:25.30,26.22 1 1456
github.com/sourcegraph/conc/pool/context_pool.go:26.22,30.17 1 17
github.com/sourcegraph/conc/pool/context_pool.go:30.17,31.33 1 17
github.com/sourcegraph/conc/pool/context_pool.go:31.33,33.14 2 2
github.com/sourcegraph/conc/pool/context_pool.go:38.3,39.36 2 1456
github.com/sourcegraph/conc/pool/context_pool.go:39.36,47.4 3 13
github.com/sourcegraph/conc/pool/context_pool.go:48.3,48.13 1 1441
github.com/sourcegraph/conc/pool/context_pool.go:54.36,58.2 2 32
github.com/sourcegraph/conc/pool/context_pool.go:64.53,68.2 3 4
github.com/sourcegraph/conc/pool/context_pool.go:78.56,82.2 3 7
github.com/sourcegraph/conc/pool/context_pool.go:87.51,92.2 4 2
github.com/sourcegraph/conc/pool/context_pool.go:96.61,100.2 3 8
github.com/sourcegraph/conc/pool/context_pool.go:102.44,104.2 1 31
github.com/sourcegraph/conc/pool/error_pool.go:27.40,28.19 1 3710
github.com/sourcegraph/conc/pool/error_pool.go:28.19,30.3 1 3710
github.com/sourcegraph/conc/pool/error_pool.go:35.34,41.20 4 54
github.com/sourcegraph/conc/pool/error_pool.go:41.20,43.3 1 21
github.com/sourcegraph/conc/pool/error_pool.go:43.8,43.29 1 30
github.com/sourcegraph/conc/pool/error_pool.go:43.29,45.3 1 5
github.com/sourcegraph/conc/pool/error_pool.go:45.8,47.3 1 25
github.com/sourcegraph/conc/pool/error_pool.go:54.67,62.2 3 2
github.com/sourcegraph/conc/pool/error_pool.go:66.49,70.2 3 5
github.com/sourcegraph/conc/pool/error_pool.go:74.57,78.2 3 14
github.com/sourcegraph/conc/pool/error_pool.go:83.39,88.2 1 33
github.com/sourcegraph/conc/pool/error_pool.go:90.42,92.2 1 60
github.com/sourcegraph/conc/pool/error_pool.go:94.39,95.16 1 3720
github.com/sourcegraph/conc/pool/error_pool.go:95.16,99.3 3 45
github.com/sourcegraph/conc/pool/pool.go:11.18,13.2 1 76
github.com/sourcegraph/conc/pool/pool.go:39.29,42.22 2 6291
github.com/sourcegraph/conc/pool/pool.go:42.22,44.10 1 423
github.com/sourcegraph/conc/pool/pool.go:45.21,45.21 0 130
github.com/sourcegraph/conc/pool/pool.go:47.11,50.23 1 293
github.com/sourcegraph/conc/pool/pool.go:50.23,52.5 1 293
github.com/sourcegraph/conc/pool/pool.go:54.8,55.10 1 5868
github.com/sourcegraph/conc/pool/pool.go:56.32,59.23 1 656
github.com/sourcegraph/conc/pool/pool.go:59.23,61.5 1 656
github.com/sourcegraph/conc/pool/pool.go:62.21,64.10 1 5212
github.com/sourcegraph/conc/pool/pool.go:72.23,79.15 3 73
github.com/sourcegraph/conc/pool/pool.go:79.15,79.43 1 73
github.com/sourcegraph/conc/pool/pool.go:81.2,81.17 1 73
github.com/sourcegraph/conc/pool/pool.go:85.36,87.2 1 1
github.com/sourcegraph/conc/pool/pool.go:91.47,93.11 2 25
github.com/sourcegraph/conc/pool/pool.go:93.11,94.62 1 1
github.com/sourcegraph/conc/pool/pool.go:96.2,97.10 2 22
github.com/sourcegraph/conc/pool/pool.go:102.23,103.23 1 6364
github.com/sourcegraph/conc/pool/pool.go:103.23,105.3 1 79
github.com/sourcegraph/conc/pool/pool.go:111.37,112.20 1 291
github.com/sourcegraph/conc/pool/pool.go:112.20,113.78 1 12
github.com/sourcegraph/conc/pool/pool.go:119.40,124.2 2 55
github.com/sourcegraph/conc/pool/pool.go:129.29,134.2 2 88
github.com/sourcegraph/conc/pool/pool.go:140.62,148.2 3 31
github.com/sourcegraph/conc/pool/pool.go:150.43,155.24 2 949
github.com/sourcegraph/conc/pool/pool.go:155.24,157.3 1 949
github.com/sourcegraph/conc/pool/pool.go:159.2,159.25 1 937
github.com/sourcegraph/conc/pool/pool.go:159.25,161.3 1 5342
github.com/sourcegraph/conc/pool/pool.go:166.30,168.2 1 1
github.com/sourcegraph/conc/pool/pool.go:170.28,171.14 1 943
github.com/sourcegraph/conc/pool/pool.go:171.14,173.3 1 656
github.com/sourcegraph/conc/pool/result_context_pool.go:22.71,24.51 2 1132
github.com/sourcegraph/conc/pool/result_context_pool.go:24.51,28.3 3 1132
github.com/sourcegraph/conc/pool/result_context_pool.go:33.52,38.2 4 16
github.com/sourcegraph/conc/pool/result_context_pool.go:43.75,47.2 3 1
github.com/sourcegraph/conc/pool/result_context_pool.go:51.71,55.2 3 1
github.com/sourcegraph/conc/pool/result_context_pool.go:60.74,64.2 3 2
github.com/sourcegraph/conc/pool/result_context_pool.go:69.69,73.2 3 1
github.com/sourcegraph/conc/pool/result_context_pool.go:77.79,81.2 3 5
github.com/sourcegraph/conc/pool/result_context_pool.go:83.53,85.2 1 10
github.com/sourcegraph/conc/pool/result_error_pool.go:24.54,26.30 2 1122
github.com/sourcegraph/conc/pool/result_error_pool.go:26.30,30.3 3 1122
github.com/sourcegraph/conc/pool/result_error_pool.go:35.50,40.2 4 11
github.com/sourcegraph/conc/pool/result_error_pool.go:45.71,49.2 3 1
github.com/sourcegraph/conc/pool/result_error_pool.go:55.85,60.2 2 1
github.com/sourcegraph/conc/pool/result_error_pool.go:64.67,68.2 3 1
github.com/sourcegraph/conc/pool/result_error_pool.go:72.75,76.2 3 5
github.com/sourcegraph/conc/pool/result_error_pool.go:78.51,80.2 1 8
github.com/sourcegraph/conc/pool/result_pool.go:13.45,17.2 1 36
github.com/sourcegraph/conc/pool/result_pool.go:32.40,34.19 2 1324
github.com/sourcegraph/conc/pool/result_pool.go:34.19,36.3 1 1324
github.com/sourcegraph/conc/pool/result_pool.go:41.36,46.2 4 9
github.com/sourcegraph/conc/pool/result_pool.go:49.45,51.2 1 0
github.com/sourcegraph/conc/pool/result_pool.go:55.58,60.2 2 12
github.com/sourcegraph/conc/pool/result_pool.go:66.80,71.2 2 15
github.com/sourcegraph/conc/pool/result_pool.go:75.65,79.2 3 5
github.com/sourcegraph/conc/pool/result_pool.go:81.46,83.2 1 32
github.com/sourcegraph/conc/pool/result_pool.go:96.47,103.2 5 3578
github.com/sourcegraph/conc/pool/result_pool.go:105.64,109.25 3 3577
github.com/sourcegraph/conc/pool/result_pool.go:109.25,113.3 3 130
github.com/sourcegraph/conc/pool/result_pool.go:115.2,117.13 2 3577
github.com/sourcegraph/conc/pool/result_pool.go:117.13,119.3 1 24
github.com/sourcegraph/conc/pool/result_pool.go:123.64,124.21 1 35
github.com/sourcegraph/conc/pool/result_pool.go:124.21,125.73 1 0
github.com/sourcegraph/conc/pool/result_pool.go:128.2,128.43 1 35
github.com/sourcegraph/conc/pool/result_pool.go:128.43,130.3 1 21
github.com/sourcegraph/conc/pool/result_pool.go:132.2,134.30 3 14
github.com/sourcegraph/conc/pool/result_pool.go:134.30,135.13 1 20
github.com/sourcegraph/conc/pool/result_pool.go:135.13,137.4 1 14
github.com/sourcegraph/conc/pool/result_pool.go:137.9,139.4 1 6
github.com/sourcegraph/conc/pool/result_pool.go:141.2,141.17 1 14
github.com/sourcegraph/conc/stream/stream.go:13.20,17.2 1 7
github.com/sourcegraph/conc/stream/stream.go:62.29,72.19 4 169
github.com/sourcegraph/conc/stream/stream.go:72.19,73.16 1 169
github.com/sourcegraph/conc/stream/stream.go:73.16,77.32 1 169
github.com/sourcegraph/conc/stream/stream.go:77.32,78.18 1 1
github.com/sourcegraph/conc/stream/stream.go:78.19,78.20 0 1
github.com/sourcegraph/conc/stream/stream.go:79.5,79.13 1 1
github.com/sourcegraph/conc/stream/stream.go:84.3,85.17 2 169
github.com/sourcegraph/conc/stream/stream.go:91.25,96.15 2 7
github.com/sourcegraph/conc/stream/stream.go:96.15,99.3 2 7
github.com/sourcegraph/conc/stream/stream.go:102.2,102.15 1 7
github.com/sourcegraph/conc/stream/stream.go:105.51,108.2 2 4
github.com/sourcegraph/conc/stream/stream.go:110.25,111.23 1 176
github.com/sourcegraph/conc/stream/stream.go:111.23,116.3 2 7
github.com/sourcegraph/conc/stream/stream.go:121.31,126.34 3 7
github.com/sourcegraph/conc/stream/stream.go:126.34,131.22 2 169
github.com/sourcegraph/conc/stream/stream.go:131.22,133.4 1 164
github.com/sourcegraph/conc/stream/stream.go:136.3,136.20 1 169
github.com/sourcegraph/conc/stream/stream.go:143.18,145.3 1 47
github.com/sourcegraph/conc/stream/stream.go:148.25,150.2 1 169
github.com/sourcegraph/conc/stream/stream.go:152.27,154.2 1 169
14 changes: 8 additions & 6 deletions iter/iter.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package iter

import (
"errors"
"runtime"
"sync"
"sync/atomic"

"github.com/sourcegraph/conc"
"github.com/sourcegraph/conc/internal/multierror"
)

// defaultMaxGoroutines returns the default maximum number of
Expand Down Expand Up @@ -127,7 +127,7 @@ func (iter Iterator[T]) ForEachIdxErr(input []T, f func(int, *T) error) error {
iter.MaxGoroutines = numInput
}

var errs error
var errs []error
var errsMu sync.Mutex
var idx atomic.Int64
var failed atomic.Bool
Expand All @@ -137,9 +137,11 @@ func (iter Iterator[T]) ForEachIdxErr(input []T, f func(int, *T) error) error {
i := int(idx.Add(1) - 1)
for ; i < numInput && !failed.Load(); i = int(idx.Add(1) - 1) {
if err := f(i, &input[i]); err != nil {
errsMu.Lock()
errs = multierror.Join(errs, err)
errsMu.Unlock()
if alreadyFailedFast := failed.Swap(iter.FailFast); !alreadyFailedFast {
errsMu.Lock()
errs = append(errs, err)
errsMu.Unlock()
}

failed.Store(iter.FailFast)
}
Expand All @@ -152,5 +154,5 @@ func (iter Iterator[T]) ForEachIdxErr(input []T, f func(int, *T) error) error {
}
wg.Wait()

return errs
return errors.Join(errs...)
}
30 changes: 15 additions & 15 deletions iter/iter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ func TestForIterator_EachIdxErr(t *testing.T) {
t.Parallel()

t.Run("failFast=false", func(t *testing.T) {
it := Iterator[int]{MaxGoroutines: 999}
it := iter.Iterator[int]{MaxGoroutines: 999}
forEach := noIndex(it.ForEachIdxErr)
testForEachErr(t, false, forEach)
})

t.Run("failFast=true", func(t *testing.T) {
it := Iterator[int]{MaxGoroutines: 999}
it := iter.Iterator[int]{MaxGoroutines: 999}
forEach := noIndex(it.ForEachIdxErr)
testForEachErr(t, true, forEach)
})
Expand All @@ -190,7 +190,7 @@ func TestForIterator_EachIdxErr(t *testing.T) {

input := []int{1, 2, 3, 4, 5}
errTest := errors.New("test error")
iterator := Iterator[int]{MaxGoroutines: 1, FailFast: true}
iterator := iter.Iterator[int]{MaxGoroutines: 1, FailFast: true}

var mu sync.Mutex
var results []int
Expand All @@ -211,7 +211,7 @@ func TestForIterator_EachIdxErr(t *testing.T) {
t.Run("safe for reuse", func(t *testing.T) {
t.Parallel()

iterator := Iterator[int]{MaxGoroutines: 999}
iterator := iter.Iterator[int]{MaxGoroutines: 999}

// iter.Concurrency > numInput case that updates iter.Concurrency
_ = iterator.ForEachIdxErr([]int{1, 2, 3}, func(i int, t *int) error {
Expand All @@ -224,12 +224,12 @@ func TestForIterator_EachIdxErr(t *testing.T) {
t.Run("allows more than defaultMaxGoroutines() concurrent tasks", func(t *testing.T) {
t.Parallel()

wantConcurrency := 2 * defaultMaxGoroutines()
wantConcurrency := 2 * iter.DefaultMaxGoroutines()

maxConcurrencyHit := make(chan struct{})

tasks := make([]int, wantConcurrency)
iterator := Iterator[int]{MaxGoroutines: wantConcurrency}
iterator := iter.Iterator[int]{MaxGoroutines: wantConcurrency}

var concurrentTasks atomic.Int64
_ = iterator.ForEachIdxErr(tasks, func(_ int, t *int) error {
Expand Down Expand Up @@ -257,19 +257,19 @@ func TestForIterator_EachErr(t *testing.T) {
t.Parallel()

t.Run("failFast=false", func(t *testing.T) {
it := Iterator[int]{MaxGoroutines: 999}
it := iter.Iterator[int]{MaxGoroutines: 999}
testForEachErr(t, false, it.ForEachErr)
})

t.Run("failFast=true", func(t *testing.T) {
it := Iterator[int]{MaxGoroutines: 999}
it := iter.Iterator[int]{MaxGoroutines: 999}
testForEachErr(t, true, it.ForEachErr)
})

t.Run("safe for reuse", func(t *testing.T) {
t.Parallel()

iterator := Iterator[int]{MaxGoroutines: 999}
iterator := iter.Iterator[int]{MaxGoroutines: 999}

// iter.Concurrency > numInput case that updates iter.Concurrency
_ = iterator.ForEachErr([]int{1, 2, 3}, func(t *int) error {
Expand All @@ -284,7 +284,7 @@ func TestForIterator_EachErr(t *testing.T) {

input := []int{1, 2, 3, 4, 5}
errTest := errors.New("test error")
iterator := Iterator[int]{MaxGoroutines: 1, FailFast: true}
iterator := iter.Iterator[int]{MaxGoroutines: 1, FailFast: true}

var mu sync.Mutex
var results []int
Expand All @@ -305,12 +305,12 @@ func TestForIterator_EachErr(t *testing.T) {
t.Run("allows more than defaultMaxGoroutines() concurrent tasks", func(t *testing.T) {
t.Parallel()

wantConcurrency := 2 * defaultMaxGoroutines()
wantConcurrency := 2 * iter.DefaultMaxGoroutines()

maxConcurrencyHit := make(chan struct{})

tasks := make([]int, wantConcurrency)
iterator := Iterator[int]{MaxGoroutines: wantConcurrency}
iterator := iter.Iterator[int]{MaxGoroutines: wantConcurrency}

var concurrentTasks atomic.Int64
_ = iterator.ForEachErr(tasks, func(t *int) error {
Expand Down Expand Up @@ -338,7 +338,7 @@ func TestForEachIdxErr(t *testing.T) {
t.Parallel()

t.Run("standart", func(t *testing.T) {
forEach := noIndex(ForEachIdxErr[int])
forEach := noIndex(iter.ForEachIdxErr[int])
testForEachErr(t, false, forEach)
})

Expand All @@ -347,7 +347,7 @@ func TestForEachIdxErr(t *testing.T) {
got := []int{}
gotMu := sync.Mutex{}

err := ForEachIdxErr(ints, func(i int, _ *int) error {
err := iter.ForEachIdxErr(ints, func(i int, _ *int) error {
gotMu.Lock()
defer gotMu.Unlock()
got = append(got, i)
Expand All @@ -362,7 +362,7 @@ func TestForEachIdxErr(t *testing.T) {
func TestForEachErr(t *testing.T) {
t.Parallel()

testForEachErr(t, false, ForEachErr[int])
testForEachErr(t, false, iter.ForEachErr[int])
}

// noIndex converts a ForEachIdxErr function (or method) into a ForEachErr function (or method).
Expand Down

0 comments on commit 1d996e3

Please sign in to comment.