Skip to content

Commit 3eb2bd7

Browse files
committed
feat: return the index of the first completed function for Race.
1 parent 325e1d4 commit 3eb2bd7

File tree

2 files changed

+34
-19
lines changed

2 files changed

+34
-19
lines changed

race.go

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,48 +7,59 @@ import (
77
"github.com/ghosind/utils"
88
)
99

10-
// Race executes the functions asynchronously, it will return the result of the first of the
11-
// finished function (including panic), and it will not send a cancel signal to other functions.
12-
func Race(funcs ...func(context.Context) error) error {
10+
// Race executes the functions asynchronously, it will return the index and the result of the first
11+
// of the finished function (including panic), and it will not send a cancel signal to other
12+
// functions.
13+
func Race(funcs ...func(context.Context) error) (int, error) {
1314
return race(context.Background(), funcs...)
1415
}
1516

16-
// RaceWithContext executes the functions asynchronously, it will return the result of the first of
17-
// the finished function (including panic), and it will not send a cancel signal to other
18-
// functions.
19-
func RaceWithContext(ctx context.Context, funcs ...func(context.Context) error) error {
17+
// RaceWithContext executes the functions asynchronously, it will return the index and the result
18+
// of the first of the finished function (including panic), and it will not send a cancel signal
19+
// to other functions.
20+
func RaceWithContext(ctx context.Context, funcs ...func(context.Context) error) (int, error) {
2021
return race(ctx, funcs...)
2122
}
2223

23-
// race executes the functions asynchronously, it will return the result of the first of the
24-
// finished function (including panic).
25-
func race(ctx context.Context, funcs ...func(context.Context) error) error {
24+
// race executes the functions asynchronously, it will return the index and the result of the first
25+
// of the finished function (including panic).
26+
func race(ctx context.Context, funcs ...func(context.Context) error) (int, error) {
2627
if len(funcs) == 0 {
27-
return nil
28+
return -1, nil
2829
}
2930

3031
if ctx == nil {
3132
ctx = context.Background()
3233
}
3334

3435
finished := atomic.Bool{}
35-
ch := make(chan error)
36+
ch := make(chan struct {
37+
Index int
38+
Error error
39+
})
3640
defer close(ch)
3741

3842
for i := 0; i < len(funcs); i++ {
3943
fn := funcs[i]
44+
n := i
4045

4146
go func() {
4247
err := utils.Try(func() error {
4348
return fn(ctx)
4449
})
4550
if finished.CompareAndSwap(false, true) {
46-
ch <- err
51+
ch <- struct {
52+
Index int
53+
Error error
54+
}{
55+
Index: n,
56+
Error: err,
57+
}
4758
}
4859
}()
4960
}
5061

51-
err := <-ch
62+
ret := <-ch
5263

53-
return err
64+
return ret.Index, ret.Error
5465
}

race_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import (
1212
func TestRaceWithoutFuncs(t *testing.T) {
1313
a := assert.New(t)
1414

15-
err := Race()
15+
index, err := Race()
1616
a.NilNow(err)
17+
a.EqualNow(index, -1)
1718
}
1819

1920
func TestRace(t *testing.T) {
@@ -30,8 +31,9 @@ func TestRace(t *testing.T) {
3031
})
3132
}
3233

33-
err := Race(funcs...)
34+
index, err := Race(funcs...)
3435
a.NilNow(err)
36+
a.EqualNow(index, 0)
3537
a.EqualNow(data, []bool{true, false, false, false, false})
3638

3739
time.Sleep(300 * time.Millisecond)
@@ -42,11 +44,12 @@ func TestRaceWithNilContext(t *testing.T) {
4244
a := assert.New(t)
4345

4446
//lint:ignore SA1012 for test case only
45-
err := RaceWithContext(nil, func(ctx context.Context) error {
47+
index, err := RaceWithContext(nil, func(ctx context.Context) error {
4648
time.Sleep(100 * time.Millisecond)
4749
return nil
4850
})
4951
a.NilNow(err)
52+
a.EqualNow(index, 0)
5053
}
5154

5255
func TestRaceWithContext(t *testing.T) {
@@ -71,8 +74,9 @@ func TestRaceWithContext(t *testing.T) {
7174
ctx, canFunc := context.WithTimeout(context.Background(), 170*time.Millisecond)
7275
defer canFunc()
7376

74-
err := RaceWithContext(ctx, funcs...)
77+
index, err := RaceWithContext(ctx, funcs...)
7578
a.NilNow(err)
79+
a.EqualNow(index, 0)
7680
a.EqualNow(data, []bool{true, false, false, false, false})
7781

7882
time.Sleep(300 * time.Millisecond)

0 commit comments

Comments
 (0)