-
Notifications
You must be signed in to change notification settings - Fork 0
/
par.go
93 lines (87 loc) · 2.15 KB
/
par.go
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* Copyright © 2013. Andy Newman.
*/
package par
import (
"sync"
)
// DO calls its arguments, functions, concurrently. Each
// argument is called from within a separate goroutine with DO only
// returning when all functions return. If no arguments are passed
// passed PAR returns immediately. And, as a small optimisation, if a
// single function is passed it is called directly from the caller's
// goroutine. Only if more than one function is supplied are any
// goroutines created.
//
// Internally DO uses a sync.WaitGroup to synchronize function
// return/goroutine termination with panics capatured to ensure
// correct wait group management.
//
func DO(f ...func()) {
switch len(f) {
case 0:
return
case 1:
if f[0] != nil {
f[0]()
}
default:
var w sync.WaitGroup
for _, fn := range f {
if fn != nil {
w.Add(1)
go func(fn func()) {
defer w.Done()
fn()
}(fn)
}
}
w.Wait()
}
}
// FOR is an iterative variaant of DO, a "parallel"
// for-loop. FOR accepts an integer range - [start, limit) - and calls
// a function, concurrently, for each value in that range. The
// function being passed a single argument, it's "index" within the
// range (an integer). Like DO() the FOR function returns when all its
// calls to the supplied function return.
//
func FOR(start, limit int, f func(int)) {
if f == nil {
return
}
switch n := limit - start; {
case n < 1:
return
case n == 1:
f(start)
return
}
var w sync.WaitGroup
for i := start; i < limit; i++ {
w.Add(1)
go func(i int) {
defer w.Done()
f(i)
}(i)
}
w.Wait()
}
// DOfn returns a function that, when called, invokes the
// DO function (aka PAR) over the arguments passed to DOfn. This
// function is for used to create functions for calls to DO.
//
func DOfn(f ...func()) func() {
return func() {
DO(f...)
}
}
// FORfn function returns a function that, when called, invokes the
// FOR "control structure" function (aka PAR_FOR) over the arguments.
// This function is for used in creating functions for calls to DO.
//
func FORfn(start, limit int, f func(int)) func() {
return func() {
FOR(start, limit, f)
}
}