@cryptotaxi247 / kubo / commits / 5bfd694ca

Remove ctxcloser

License: MIT Signed-off-by: rht <rhtbot@gmail.com>

rht committed Jun 15, 2015 at 20:00 UTC 5bfd694ca70cfea3cff9091a5874d92a85fbea37
1 file changed -183
util/ctxcloser/closer.go deleted
-183
@@ -1,183 +0,0 @@
1 -package ctxcloser
2 -
3 -import (
4 - "sync"
5 -
6 - context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
7 -)
8 -
9 -// CloseFunc is a function used to close a ContextCloser
10 -type CloseFunc func() error
11 -
12 -var nilCloseFunc = func() error { return nil }
13 -
14 -// ContextCloser is an interface for services able to be opened and closed.
15 -// It has a parent Context, and Children. But ContextCloser is not a proper
16 -// "tree" like the Context tree. It is more like a Context-WaitGroup hybrid.
17 -// It models a main object with a few children objects -- and, unlike the
18 -// context -- concerns itself with the parent-child closing semantics:
19 -//
20 -// - Can define a CloseFunc (func() error) to be run at Close time.
21 -// - Children call Children().Add(1) to be waited upon
22 -// - Children can select on <-Closing() to know when they should shut down.
23 -// - Close() will wait until all children call Children().Done()
24 -// - <-Closed() signals when the service is completely closed.
25 -//
26 -// ContextCloser can be embedded into the main object itself. In that case,
27 -// the closeFunc (if a member function) has to be set after the struct
28 -// is intialized:
29 -//
30 -// type service struct {
31 -// ContextCloser
32 -// net.Conn
33 -// }
34 -//
35 -// func (s *service) close() error {
36 -// return s.Conn.Close()
37 -// }
38 -//
39 -// func newService(ctx context.Context, c net.Conn) *service {
40 -// s := &service{c}
41 -// s.ContextCloser = NewContextCloser(ctx, s.close)
42 -// return s
43 -// }
44 -//
45 -type ContextCloser interface {
46 -
47 - // Context is the context of this ContextCloser. It is "sort of" a parent.
48 - Context() context.Context
49 -
50 - // Children is a sync.Waitgroup for all children goroutines that should
51 - // shut down completely before this service is said to be "closed".
52 - // Follows the semantics of WaitGroup:
53 - //
54 - // Children().Add(1) // add one more dependent child
55 - // Children().Done() // child signals it is done
56 - //
57 - Children() *sync.WaitGroup
58 -
59 - // AddCloserChild registers a dependent ContextCloser child. The child will
60 - // be closed when this parent is closed, and waited upon to finish. It is
61 - // the functional equivalent of the following:
62 - //
63 - // go func(parent, child ContextCloser) {
64 - // parent.Children().Add(1) // add one more dependent child
65 - // <-parent.Closing() // wait until parent is closing
66 - // child.Close() // signal child to close
67 - // parent.Children().Done() // child signals it is done
68 - // }(a, b)
69 - //
70 - AddCloserChild(c ContextCloser)
71 -
72 - // Close is a method to call when you wish to stop this ContextCloser
73 - Close() error
74 -
75 - // Closing is a signal to wait upon, like Context.Done().
76 - // It fires when the object should be closing (but hasn't yet fully closed).
77 - // The primary use case is for child goroutines who need to know when
78 - // they should shut down. (equivalent to Context().Done())
79 - Closing() <-chan struct{}
80 -
81 - // Closed is a method to wait upon, like Context.Done().
82 - // It fires when the entire object is fully closed.
83 - // The primary use case is for external listeners who need to know when
84 - // this object is completly done, and all its children closed.
85 - Closed() <-chan struct{}
86 -}
87 -
88 -// contextCloser is an OpenCloser with a cancellable context
89 -type contextCloser struct {
90 - ctx context.Context
91 - cancel context.CancelFunc
92 -
93 - // called to run the close logic.
94 - closeFunc CloseFunc
95 -
96 - // closed is released once the close function is done.
97 - closed chan struct{}
98 -
99 - // wait group for child goroutines
100 - children sync.WaitGroup
101 -
102 - // sync primitive to ensure the close logic is only called once.
103 - closeOnce sync.Once
104 -
105 - // error to return to clients of Close().
106 - closeErr error
107 -}
108 -
109 -// NewContextCloser constructs and returns a ContextCloser. It will call
110 -// cf CloseFunc before its Done() Wait signals fire.
111 -func NewContextCloser(ctx context.Context, cf CloseFunc) ContextCloser {
112 - if cf == nil {
113 - cf = nilCloseFunc
114 - }
115 - ctx, cancel := context.WithCancel(ctx)
116 - c := &contextCloser{
117 - ctx: ctx,
118 - cancel: cancel,
119 - closeFunc: cf,
120 - closed: make(chan struct{}),
121 - }
122 -
123 - c.Children().Add(1) // we're a child goroutine, to be waited upon.
124 - go c.closeOnContextDone()
125 - return c
126 -}
127 -
128 -func (c *contextCloser) Context() context.Context {
129 - return c.ctx
130 -}
131 -
132 -func (c *contextCloser) Children() *sync.WaitGroup {
133 - return &c.children
134 -}
135 -
136 -func (c *contextCloser) AddCloserChild(child ContextCloser) {
137 - c.children.Add(1)
138 - go func(parent, child ContextCloser) {
139 - <-parent.Closing() // wait until parent is closing
140 - child.Close() // signal child to close
141 - parent.Children().Done() // child signals it is done
142 - }(c, child)
143 -}
144 -
145 -// Close is the external close function. it's a wrapper around internalClose
146 -// that waits on Closed()
147 -func (c *contextCloser) Close() error {
148 - c.internalClose()
149 - <-c.Closed() // wait until we're totally done.
150 - return c.closeErr
151 -}
152 -
153 -func (c *contextCloser) Closing() <-chan struct{} {
154 - return c.Context().Done()
155 -}
156 -
157 -func (c *contextCloser) Closed() <-chan struct{} {
158 - return c.closed
159 -}
160 -
161 -func (c *contextCloser) internalClose() {
162 - go c.closeOnce.Do(c.closeLogic)
163 -}
164 -
165 -// the _actual_ close process.
166 -func (c *contextCloser) closeLogic() {
167 - // this function should only be called once (hence the sync.Once).
168 - // and it will panic at the bottom (on close(c.closed)) otherwise.
169 -
170 - c.cancel() // signal that we're shutting down (Closing)
171 - c.closeErr = c.closeFunc() // actually run the close logic
172 - c.children.Wait() // wait till all children are done.
173 - close(c.closed) // signal that we're shut down (Closed)
174 -}
175 -
176 -// if parent context is shut down before we call Close explicitly,
177 -// we need to go through the Close motions anyway. Hence all the sync
178 -// stuff all over the place...
179 -func (c *contextCloser) closeOnContextDone() {
180 - <-c.Context().Done() // wait until parent (context) is done.
181 - c.internalClose()
182 - c.Children().Done()
183 -}