exec

package
v0.0.0-...-d2438c5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 20, 2019 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Block

func Block(g *Group)

Block creates a blocking executional group that waits until some other group action finishing, causing the closing of the group action.

func Interrupt

func Interrupt(g *Group) <-chan struct{}

Interrupt creates a blocking executional group that becomes free if a interrupt or terminate os signal is received.

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 NewGroup

func NewGroup() *Group

NewGroup creates a new group

func (*Group) Add

func (g *Group) Add(execute func() error, interrupt func(error))

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:

func (*Group) Run

func (g *Group) Run() error

Run all actions (functions) concurrently. When the first action returns, all others are interrupted. Run only returns when all actions have exited. Run returns the error returned by the first existing action.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL