blob: 91501f9cb78a99c2983867c22f6832146b773964 (
plain)
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
|
package sync
import "context"
func OrDone[T any](ctx context.Context, in <-chan T) <-chan T {
if in == nil {
// we only expect this to happen during development
panic("in-channel is nil")
}
out := make(chan T)
go func() {
defer close(out)
for {
v, ok := CancelOrReceive(ctx, in)
if !ok {
return
}
if !CancelOrSend(ctx, out, v) {
return
}
}
}()
return out
}
// CancelOrReceive is trying to solve the same problem as OrDone but does so
// without an extra goroutine.
func CancelOrReceive[T any](ctx context.Context, in <-chan T) (v T, ok bool) {
select {
case <-ctx.Done():
return // <zero value of type T>, false
case v, ok = <-in:
return // v, ok
}
}
// CancelOrSend is a helper function to simplify sending values to channels
// while keeping the context in mind.
func CancelOrSend[T any](ctx context.Context, out chan<- T, val T) bool {
select {
case <-ctx.Done():
return false
case out <- val:
return true
}
}
|