-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsingle.go
59 lines (51 loc) · 1.68 KB
/
single.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
package taskgroup
// A Single manages a single background goroutine. The task is started when the
// value is first created, and the caller can use the Wait method to block
// until it has exited.
type Single[T any] struct {
valc chan T
val T
}
// Wait blocks until the task monitored by s has completed and returns the
// value it reported.
func (s *Single[T]) Wait() T {
if v, ok := <-s.valc; ok {
// This is the first call to receive a value:
// Update val and close the channel (in that order).
s.val = v
close(s.valc)
}
return s.val
}
// Go runs task in a new goroutine. The caller must call Wait to wait for the
// task to return and collect its value.
func Go[T any](task func() T) *Single[T] {
// N.B. This is closed by Wait.
valc := make(chan T, 1)
go func() { valc <- task() }()
return &Single[T]{valc: valc}
}
// Run runs task in a new goroutine. The caller must call Wait to wait for the
// task to return. The error reported by Wait is always nil.
func Run(task func()) *Single[error] { return Go(noError(task)) }
// Call starts task in a new goroutine. The caller must call Wait to wait for
// the task to return and collect its result.
func Call[T any](task func() (T, error)) *Single[Result[T]] {
return Go(func() Result[T] {
v, err := task()
return Result[T]{Value: v, Err: err}
})
}
// A Result is a pair of an arbitrary value and an error.
type Result[T any] struct {
Value T
Err error
}
// Get returns the fields of r as results. It is a convenience method for
// unpacking the results of a Call.
//
// Typical usage:
//
// s := taskgroup.Call(func() (int, error) { ... })
// v, err := s.Wait().Get()
func (r Result[T]) Get() (T, error) { return r.Value, r.Err }