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
-}