diff options
Diffstat (limited to 'vendor/golang.org/x/net/context/pre_go17.go')
-rw-r--r-- | vendor/golang.org/x/net/context/pre_go17.go | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go new file mode 100644 index 0000000..0f35592 --- /dev/null +++ b/vendor/golang.org/x/net/context/pre_go17.go | |||
@@ -0,0 +1,300 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.7 | ||
6 | |||
7 | package context | ||
8 | |||
9 | import ( | ||
10 | "errors" | ||
11 | "fmt" | ||
12 | "sync" | ||
13 | "time" | ||
14 | ) | ||
15 | |||
16 | // An emptyCtx is never canceled, has no values, and has no deadline. It is not | ||
17 | // struct{}, since vars of this type must have distinct addresses. | ||
18 | type emptyCtx int | ||
19 | |||
20 | func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { | ||
21 | return | ||
22 | } | ||
23 | |||
24 | func (*emptyCtx) Done() <-chan struct{} { | ||
25 | return nil | ||
26 | } | ||
27 | |||
28 | func (*emptyCtx) Err() error { | ||
29 | return nil | ||
30 | } | ||
31 | |||
32 | func (*emptyCtx) Value(key interface{}) interface{} { | ||
33 | return nil | ||
34 | } | ||
35 | |||
36 | func (e *emptyCtx) String() string { | ||
37 | switch e { | ||
38 | case background: | ||
39 | return "context.Background" | ||
40 | case todo: | ||
41 | return "context.TODO" | ||
42 | } | ||
43 | return "unknown empty Context" | ||
44 | } | ||
45 | |||
46 | var ( | ||
47 | background = new(emptyCtx) | ||
48 | todo = new(emptyCtx) | ||
49 | ) | ||
50 | |||
51 | // Canceled is the error returned by Context.Err when the context is canceled. | ||
52 | var Canceled = errors.New("context canceled") | ||
53 | |||
54 | // DeadlineExceeded is the error returned by Context.Err when the context's | ||
55 | // deadline passes. | ||
56 | var DeadlineExceeded = errors.New("context deadline exceeded") | ||
57 | |||
58 | // WithCancel returns a copy of parent with a new Done channel. The returned | ||
59 | // context's Done channel is closed when the returned cancel function is called | ||
60 | // or when the parent context's Done channel is closed, whichever happens first. | ||
61 | // | ||
62 | // Canceling this context releases resources associated with it, so code should | ||
63 | // call cancel as soon as the operations running in this Context complete. | ||
64 | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { | ||
65 | c := newCancelCtx(parent) | ||
66 | propagateCancel(parent, c) | ||
67 | return c, func() { c.cancel(true, Canceled) } | ||
68 | } | ||
69 | |||
70 | // newCancelCtx returns an initialized cancelCtx. | ||
71 | func newCancelCtx(parent Context) *cancelCtx { | ||
72 | return &cancelCtx{ | ||
73 | Context: parent, | ||
74 | done: make(chan struct{}), | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // propagateCancel arranges for child to be canceled when parent is. | ||
79 | func propagateCancel(parent Context, child canceler) { | ||
80 | if parent.Done() == nil { | ||
81 | return // parent is never canceled | ||
82 | } | ||
83 | if p, ok := parentCancelCtx(parent); ok { | ||
84 | p.mu.Lock() | ||
85 | if p.err != nil { | ||
86 | // parent has already been canceled | ||
87 | child.cancel(false, p.err) | ||
88 | } else { | ||
89 | if p.children == nil { | ||
90 | p.children = make(map[canceler]bool) | ||
91 | } | ||
92 | p.children[child] = true | ||
93 | } | ||
94 | p.mu.Unlock() | ||
95 | } else { | ||
96 | go func() { | ||
97 | select { | ||
98 | case <-parent.Done(): | ||
99 | child.cancel(false, parent.Err()) | ||
100 | case <-child.Done(): | ||
101 | } | ||
102 | }() | ||
103 | } | ||
104 | } | ||
105 | |||
106 | // parentCancelCtx follows a chain of parent references until it finds a | ||
107 | // *cancelCtx. This function understands how each of the concrete types in this | ||
108 | // package represents its parent. | ||
109 | func parentCancelCtx(parent Context) (*cancelCtx, bool) { | ||
110 | for { | ||
111 | switch c := parent.(type) { | ||
112 | case *cancelCtx: | ||
113 | return c, true | ||
114 | case *timerCtx: | ||
115 | return c.cancelCtx, true | ||
116 | case *valueCtx: | ||
117 | parent = c.Context | ||
118 | default: | ||
119 | return nil, false | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | // removeChild removes a context from its parent. | ||
125 | func removeChild(parent Context, child canceler) { | ||
126 | p, ok := parentCancelCtx(parent) | ||
127 | if !ok { | ||
128 | return | ||
129 | } | ||
130 | p.mu.Lock() | ||
131 | if p.children != nil { | ||
132 | delete(p.children, child) | ||
133 | } | ||
134 | p.mu.Unlock() | ||
135 | } | ||
136 | |||
137 | // A canceler is a context type that can be canceled directly. The | ||
138 | // implementations are *cancelCtx and *timerCtx. | ||
139 | type canceler interface { | ||
140 | cancel(removeFromParent bool, err error) | ||
141 | Done() <-chan struct{} | ||
142 | } | ||
143 | |||
144 | // A cancelCtx can be canceled. When canceled, it also cancels any children | ||
145 | // that implement canceler. | ||
146 | type cancelCtx struct { | ||
147 | Context | ||
148 | |||
149 | done chan struct{} // closed by the first cancel call. | ||
150 | |||
151 | mu sync.Mutex | ||
152 | children map[canceler]bool // set to nil by the first cancel call | ||
153 | err error // set to non-nil by the first cancel call | ||
154 | } | ||
155 | |||
156 | func (c *cancelCtx) Done() <-chan struct{} { | ||
157 | return c.done | ||
158 | } | ||
159 | |||
160 | func (c *cancelCtx) Err() error { | ||
161 | c.mu.Lock() | ||
162 | defer c.mu.Unlock() | ||
163 | return c.err | ||
164 | } | ||
165 | |||
166 | func (c *cancelCtx) String() string { | ||
167 | return fmt.Sprintf("%v.WithCancel", c.Context) | ||
168 | } | ||
169 | |||
170 | // cancel closes c.done, cancels each of c's children, and, if | ||
171 | // removeFromParent is true, removes c from its parent's children. | ||
172 | func (c *cancelCtx) cancel(removeFromParent bool, err error) { | ||
173 | if err == nil { | ||
174 | panic("context: internal error: missing cancel error") | ||
175 | } | ||
176 | c.mu.Lock() | ||
177 | if c.err != nil { | ||
178 | c.mu.Unlock() | ||
179 | return // already canceled | ||
180 | } | ||
181 | c.err = err | ||
182 | close(c.done) | ||
183 | for child := range c.children { | ||
184 | // NOTE: acquiring the child's lock while holding parent's lock. | ||
185 | child.cancel(false, err) | ||
186 | } | ||
187 | c.children = nil | ||
188 | c.mu.Unlock() | ||
189 | |||
190 | if removeFromParent { | ||
191 | removeChild(c.Context, c) | ||
192 | } | ||
193 | } | ||
194 | |||
195 | // WithDeadline returns a copy of the parent context with the deadline adjusted | ||
196 | // to be no later than d. If the parent's deadline is already earlier than d, | ||
197 | // WithDeadline(parent, d) is semantically equivalent to parent. The returned | ||
198 | // context's Done channel is closed when the deadline expires, when the returned | ||
199 | // cancel function is called, or when the parent context's Done channel is | ||
200 | // closed, whichever happens first. | ||
201 | // | ||
202 | // Canceling this context releases resources associated with it, so code should | ||
203 | // call cancel as soon as the operations running in this Context complete. | ||
204 | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { | ||
205 | if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { | ||
206 | // The current deadline is already sooner than the new one. | ||
207 | return WithCancel(parent) | ||
208 | } | ||
209 | c := &timerCtx{ | ||
210 | cancelCtx: newCancelCtx(parent), | ||
211 | deadline: deadline, | ||
212 | } | ||
213 | propagateCancel(parent, c) | ||
214 | d := deadline.Sub(time.Now()) | ||
215 | if d <= 0 { | ||
216 | c.cancel(true, DeadlineExceeded) // deadline has already passed | ||
217 | return c, func() { c.cancel(true, Canceled) } | ||
218 | } | ||
219 | c.mu.Lock() | ||
220 | defer c.mu.Unlock() | ||
221 | if c.err == nil { | ||
222 | c.timer = time.AfterFunc(d, func() { | ||
223 | c.cancel(true, DeadlineExceeded) | ||
224 | }) | ||
225 | } | ||
226 | return c, func() { c.cancel(true, Canceled) } | ||
227 | } | ||
228 | |||
229 | // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to | ||
230 | // implement Done and Err. It implements cancel by stopping its timer then | ||
231 | // delegating to cancelCtx.cancel. | ||
232 | type timerCtx struct { | ||
233 | *cancelCtx | ||
234 | timer *time.Timer // Under cancelCtx.mu. | ||
235 | |||
236 | deadline time.Time | ||
237 | } | ||
238 | |||
239 | func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { | ||
240 | return c.deadline, true | ||
241 | } | ||
242 | |||
243 | func (c *timerCtx) String() string { | ||
244 | return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) | ||
245 | } | ||
246 | |||
247 | func (c *timerCtx) cancel(removeFromParent bool, err error) { | ||
248 | c.cancelCtx.cancel(false, err) | ||
249 | if removeFromParent { | ||
250 | // Remove this timerCtx from its parent cancelCtx's children. | ||
251 | removeChild(c.cancelCtx.Context, c) | ||
252 | } | ||
253 | c.mu.Lock() | ||
254 | if c.timer != nil { | ||
255 | c.timer.Stop() | ||
256 | c.timer = nil | ||
257 | } | ||
258 | c.mu.Unlock() | ||
259 | } | ||
260 | |||
261 | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). | ||
262 | // | ||
263 | // Canceling this context releases resources associated with it, so code should | ||
264 | // call cancel as soon as the operations running in this Context complete: | ||
265 | // | ||
266 | // func slowOperationWithTimeout(ctx context.Context) (Result, error) { | ||
267 | // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) | ||
268 | // defer cancel() // releases resources if slowOperation completes before timeout elapses | ||
269 | // return slowOperation(ctx) | ||
270 | // } | ||
271 | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { | ||
272 | return WithDeadline(parent, time.Now().Add(timeout)) | ||
273 | } | ||
274 | |||
275 | // WithValue returns a copy of parent in which the value associated with key is | ||
276 | // val. | ||
277 | // | ||
278 | // Use context Values only for request-scoped data that transits processes and | ||
279 | // APIs, not for passing optional parameters to functions. | ||
280 | func WithValue(parent Context, key interface{}, val interface{}) Context { | ||
281 | return &valueCtx{parent, key, val} | ||
282 | } | ||
283 | |||
284 | // A valueCtx carries a key-value pair. It implements Value for that key and | ||
285 | // delegates all other calls to the embedded Context. | ||
286 | type valueCtx struct { | ||
287 | Context | ||
288 | key, val interface{} | ||
289 | } | ||
290 | |||
291 | func (c *valueCtx) String() string { | ||
292 | return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) | ||
293 | } | ||
294 | |||
295 | func (c *valueCtx) Value(key interface{}) interface{} { | ||
296 | if c.key == key { | ||
297 | return c.val | ||
298 | } | ||
299 | return c.Context.Value(key) | ||
300 | } | ||