Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group collects actions (functions) and runs them concurrently. When one action (function) returns, all actions are interrupted. The zero value of a Group is useful.
func (*Group) Add ¶
Add an action (function) to the group. Each action must be pre-emptable by an interrupt function. That is, if interrupt is invoked, execute should return. Also is must be safe to call interrupt even after execute has returned.
The first action (function) to return interrupts all running actions. The error is passed to the interrupt functions and is returned by Run.
Example (Basic) ¶
package main import ( "fmt" "time" "github.com/pkg/errors" "github.com/spoke-d/thermionic/internal/exec" ) func main() { var g exec.Group { cancel := make(chan struct{}) g.Add(func() error { select { case <-time.After(time.Second): fmt.Println("The first actor had its time elapsed") return nil case <-cancel: fmt.Println("The first actor was canceled") return nil } }, func(err error) { fmt.Printf("The first actor was interrupted with: %v\n", err) close(cancel) }) } { g.Add(func() error { fmt.Println("The second actor is returning immediately") return errors.New("immediate teardown") }, func(err error) { // Note that this interrupt function is called even though the // corresponding execute function has already returned. fmt.Printf("The second actor was interrupted with: %v\n", err) }) } fmt.Printf("The group was terminated with: %v\n", g.Run()) }
Output: The second actor is returning immediately The first actor was interrupted with: immediate teardown The second actor was interrupted with: immediate teardown The first actor was canceled The group was terminated with: immediate teardown
Example (Context) ¶
package main import ( "context" "fmt" "github.com/spoke-d/thermionic/internal/exec" ) func main() { runUntilCanceled := func(ctx context.Context) error { <-ctx.Done() return ctx.Err() } ctx, cancel := context.WithCancel(context.Background()) var g exec.Group { ctx, cancel := context.WithCancel(ctx) // note: shadowed g.Add(func() error { return runUntilCanceled(ctx) }, func(error) { cancel() }) } go cancel() fmt.Printf("The group was terminated with: %v\n", g.Run()) }
Output: The group was terminated with: context canceled
Example (Listener) ¶
package main import ( "fmt" "net" "net/http" "github.com/pkg/errors" "github.com/spoke-d/thermionic/internal/exec" ) func main() { var g exec.Group { ln, _ := net.Listen("tcp", ":0") g.Add(func() error { defer fmt.Println("http.Serve returned") return http.Serve(ln, http.NewServeMux()) }, func(error) { ln.Close() }) } { g.Add(func() error { return errors.New("immediate teardown") }, func(error) { // Nothing. }) } }
Output:
Click to show internal directories.
Click to hide internal directories.