Hunter0x7c7
2022-08-11 b8230139fb40edea387617b6accd8371e37eda58
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package task
 
import (
    "context"
 
    "github.com/v2fly/v2ray-core/v5/common/signal/semaphore"
)
 
// OnSuccess executes g() after f() returns nil.
func OnSuccess(f func() error, g func() error) func() error {
    return func() error {
        if err := f(); err != nil {
            return err
        }
        return g()
    }
}
 
// Run executes a list of tasks in parallel, returns the first error encountered or nil if all tasks pass.
func Run(ctx context.Context, tasks ...func() error) error {
    n := len(tasks)
    s := semaphore.New(n)
    done := make(chan error, 1)
 
    for _, task := range tasks {
        <-s.Wait()
        go func(f func() error) {
            err := f()
            if err == nil {
                s.Signal()
                return
            }
 
            select {
            case done <- err:
            default:
            }
        }(task)
    }
 
    for i := 0; i < n; i++ {
        select {
        case err := <-done:
            return err
        case <-ctx.Done():
            return ctx.Err()
        case <-s.Wait():
        }
    }
 
    return nil
}