-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpmap.go
More file actions
60 lines (47 loc) · 1.22 KB
/
pmap.go
File metadata and controls
60 lines (47 loc) · 1.22 KB
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
package main
import (
"context"
"fmt"
"sync/atomic"
"time"
"golang.org/x/sync/semaphore"
)
func main() {
start := time.Now()
vals := PMap(int2str, []int{1, 2, 3, 4, 5, 6, 7, 8, 9}, 3)
fmt.Printf("%#v\n", vals) // []string{"1", "2", "3", "4", "5", "6", "7", "8", "9"}
fmt.Println(time.Since(start))
start = time.Now()
iVals := PMap(inc, []int{1, 2, 3, 4, 5, 6, 7, 8, 9}, 3)
fmt.Printf("%#v\n", iVals) // [int]{2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println(time.Since(start))
}
var nInc atomic.Int32
func inc(n int) int {
nInc.Add(1)
defer nInc.Add(-1)
fmt.Println("inc:", nInc.Load())
time.Sleep(100 * time.Millisecond)
return n + 1
}
func int2str(i int) string {
time.Sleep(100 * time.Millisecond)
return fmt.Sprintf("%d", i)
}
// PMap returns the application of "fn" on every element of values.
// It will run up to "n" goroutines at the same time.
// Use golang.org/x/sync/semaphore
func PMap[V any, R any](fn func(V) R, values []V, n int) []R {
sema := semaphore.NewWeighted(int64(n))
out := make([]R, len(values))
for i, v := range values {
sema.Acquire(context.Background(), 1)
go func() {
defer sema.Release(1)
out[i] = fn(v)
}()
}
sema.Acquire(context.Background(), int64(n))
// wait
return out
}