• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.gx/H24-Mar-2020-21

context/H24-Mar-2020-332215

periodic/H24-Mar-2020-585380

ratelimit/H24-Mar-2020-173108

.travis.ymlH A D24-Mar-202076 106

LICENSEH A D24-Mar-20201.1 KiB2217

README.mdH A D24-Mar-20205 KiB133119

background.goH A D24-Mar-20201,002 3425

example_test.goH A D24-Mar-2020526 3824

go.modH A D24-Mar-202087 63

go.sumH A D24-Mar-2020171 32

goprocess.goH A D24-Mar-20208.8 KiB26463

goprocess_test.goH A D24-Mar-202014.2 KiB789627

impl-mutex.goH A D24-Mar-20207 KiB300203

link.goH A D24-Mar-20202.5 KiB12988

package.jsonH A D24-Mar-2020267 1514

README.md

1# goprocess - lifecycles in go
2
3[![travisbadge](https://travis-ci.org/jbenet/goprocess.svg)](https://travis-ci.org/jbenet/goprocess)
4
5(Based on https://github.com/jbenet/go-ctxgroup)
6
7- Godoc: https://godoc.org/github.com/jbenet/goprocess
8
9`goprocess` introduces a way to manage process lifecycles in go. It is
10much like [go.net/context](https://godoc.org/code.google.com/p/go.net/context)
11(it actually uses a Context), but it is more like a Context-WaitGroup hybrid.
12`goprocess` is about being able to start and stop units of work, which may
13receive `Close` signals from many clients. Think of it like a UNIX process
14tree, but inside go.
15
16`goprocess` seeks to minimally affect your objects, so you can use it
17with both embedding or composition. At the heart of `goprocess` is the
18`Process` interface:
19
20```Go
21// Process is the basic unit of work in goprocess. It defines a computation
22// with a lifecycle:
23// - running (before calling Close),
24// - closing (after calling Close at least once),
25// - closed (after Close returns, and all teardown has _completed_).
26//
27// More specifically, it fits this:
28//
29//   p := WithTeardown(tf) // new process is created, it is now running.
30//   p.AddChild(q)         // can register children **before** Closing.
31//   go p.Close()          // blocks until done running teardown func.
32//   <-p.Closing()         // would now return true.
33//   <-p.childrenDone()    // wait on all children to be done
34//   p.teardown()          // runs the user's teardown function tf.
35//   p.Close()             // now returns, with error teardown returned.
36//   <-p.Closed()          // would now return true.
37//
38// Processes can be arranged in a process "tree", where children are
39// automatically Closed if their parents are closed. (Note, it is actually
40// a Process DAG, children may have multiple parents). A process may also
41// optionally wait for another to fully Close before beginning to Close.
42// This makes it easy to ensure order of operations and proper sequential
43// teardown of resurces. For example:
44//
45//   p1 := goprocess.WithTeardown(func() error {
46//     fmt.Println("closing 1")
47//   })
48//   p2 := goprocess.WithTeardown(func() error {
49//     fmt.Println("closing 2")
50//   })
51//   p3 := goprocess.WithTeardown(func() error {
52//     fmt.Println("closing 3")
53//   })
54//
55//   p1.AddChild(p2)
56//   p2.AddChild(p3)
57//
58//
59//   go p1.Close()
60//   go p2.Close()
61//   go p3.Close()
62//
63//   // Output:
64//   // closing 3
65//   // closing 2
66//   // closing 1
67//
68// Process is modelled after the UNIX processes group idea, and heavily
69// informed by sync.WaitGroup and go.net/context.Context.
70//
71// In the function documentation of this interface, `p` always refers to
72// the self Process.
73type Process interface {
74
75  // WaitFor makes p wait for q before exiting. Thus, p will _always_ close
76  // _after_ q. Note well: a waiting cycle is deadlock.
77  //
78  // If q is already Closed, WaitFor calls p.Close()
79  // If p is already Closing or Closed, WaitFor panics. This is the same thing
80  // as calling Add(1) _after_ calling Done() on a wait group. Calling WaitFor
81  // on an already-closed process is a programming error likely due to bad
82  // synchronization
83  WaitFor(q Process)
84
85  // AddChildNoWait registers child as a "child" of Process. As in UNIX,
86  // when parent is Closed, child is Closed -- child may Close beforehand.
87  // This is the equivalent of calling:
88  //
89  //  go func(parent, child Process) {
90  //    <-parent.Closing()
91  //    child.Close()
92  //  }(p, q)
93  //
94  // Note: the naming of functions is `AddChildNoWait` and `AddChild` (instead
95  // of `AddChild` and `AddChildWaitFor`) because:
96  // - it is the more common operation,
97  // - explicitness is helpful in the less common case (no waiting), and
98  // - usual "child" semantics imply parent Processes should wait for children.
99  AddChildNoWait(q Process)
100
101  // AddChild is the equivalent of calling:
102  //  parent.AddChildNoWait(q)
103  //  parent.WaitFor(q)
104  AddChild(q Process)
105
106  // Go creates a new process, adds it as a child, and spawns the ProcessFunc f
107  // in its own goroutine. It is equivalent to:
108  //
109  //   GoChild(p, f)
110  //
111  // It is useful to construct simple asynchronous workers, children of p.
112  Go(f ProcessFunc) Process
113
114  // Close ends the process. Close blocks until the process has completely
115  // shut down, and any teardown has run _exactly once_. The returned error
116  // is available indefinitely: calling Close twice returns the same error.
117  // If the process has already been closed, Close returns immediately.
118  Close() error
119
120  // Closing is a signal to wait upon. The returned channel is closed
121  // _after_ Close has been called at least once, but teardown may or may
122  // not be done yet. The primary use case of Closing is for children who
123  // need to know when a parent is shutting down, and therefore also shut
124  // down.
125  Closing() <-chan struct{}
126
127  // Closed is a signal to wait upon. The returned channel is closed
128  // _after_ Close has completed; teardown has finished. The primary use case
129  // of Closed is waiting for a Process to Close without _causing_ the Close.
130  Closed() <-chan struct{}
131}
132```
133