]>
Commit | Line | Data |
---|---|---|
9b12e4fe JC |
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 | // Package context defines the Context type, which carries deadlines, | |
6 | // cancelation signals, and other request-scoped values across API boundaries | |
7 | // and between processes. | |
8 | // | |
9 | // Incoming requests to a server should create a Context, and outgoing calls to | |
10 | // servers should accept a Context. The chain of function calls between must | |
11 | // propagate the Context, optionally replacing it with a modified copy created | |
12 | // using WithDeadline, WithTimeout, WithCancel, or WithValue. | |
13 | // | |
14 | // Programs that use Contexts should follow these rules to keep interfaces | |
15 | // consistent across packages and enable static analysis tools to check context | |
16 | // propagation: | |
17 | // | |
18 | // Do not store Contexts inside a struct type; instead, pass a Context | |
19 | // explicitly to each function that needs it. The Context should be the first | |
20 | // parameter, typically named ctx: | |
21 | // | |
22 | // func DoSomething(ctx context.Context, arg Arg) error { | |
23 | // // ... use ctx ... | |
24 | // } | |
25 | // | |
26 | // Do not pass a nil Context, even if a function permits it. Pass context.TODO | |
27 | // if you are unsure about which Context to use. | |
28 | // | |
29 | // Use context Values only for request-scoped data that transits processes and | |
30 | // APIs, not for passing optional parameters to functions. | |
31 | // | |
32 | // The same Context may be passed to functions running in different goroutines; | |
33 | // Contexts are safe for simultaneous use by multiple goroutines. | |
34 | // | |
35 | // See http://blog.golang.org/context for example code for a server that uses | |
36 | // Contexts. | |
37 | package context // import "github.com/fsouza/go-dockerclient/external/golang.org/x/net/context" | |
38 | ||
39 | import ( | |
40 | "errors" | |
41 | "fmt" | |
42 | "sync" | |
43 | "time" | |
44 | ) | |
45 | ||
46 | // A Context carries a deadline, a cancelation signal, and other values across | |
47 | // API boundaries. | |
48 | // | |
49 | // Context's methods may be called by multiple goroutines simultaneously. | |
50 | type Context interface { | |
51 | // Deadline returns the time when work done on behalf of this context | |
52 | // should be canceled. Deadline returns ok==false when no deadline is | |
53 | // set. Successive calls to Deadline return the same results. | |
54 | Deadline() (deadline time.Time, ok bool) | |
55 | ||
56 | // Done returns a channel that's closed when work done on behalf of this | |
57 | // context should be canceled. Done may return nil if this context can | |
58 | // never be canceled. Successive calls to Done return the same value. | |
59 | // | |
60 | // WithCancel arranges for Done to be closed when cancel is called; | |
61 | // WithDeadline arranges for Done to be closed when the deadline | |
62 | // expires; WithTimeout arranges for Done to be closed when the timeout | |
63 | // elapses. | |
64 | // | |
65 | // Done is provided for use in select statements: | |
66 | // | |
67 | // // Stream generates values with DoSomething and sends them to out | |
68 | // // until DoSomething returns an error or ctx.Done is closed. | |
69 | // func Stream(ctx context.Context, out <-chan Value) error { | |
70 | // for { | |
71 | // v, err := DoSomething(ctx) | |
72 | // if err != nil { | |
73 | // return err | |
74 | // } | |
75 | // select { | |
76 | // case <-ctx.Done(): | |
77 | // return ctx.Err() | |
78 | // case out <- v: | |
79 | // } | |
80 | // } | |
81 | // } | |
82 | // | |
83 | // See http://blog.golang.org/pipelines for more examples of how to use | |
84 | // a Done channel for cancelation. | |
85 | Done() <-chan struct{} | |
86 | ||
87 | // Err returns a non-nil error value after Done is closed. Err returns | |
88 | // Canceled if the context was canceled or DeadlineExceeded if the | |
89 | // context's deadline passed. No other values for Err are defined. | |
90 | // After Done is closed, successive calls to Err return the same value. | |
91 | Err() error | |
92 | ||
93 | // Value returns the value associated with this context for key, or nil | |
94 | // if no value is associated with key. Successive calls to Value with | |
95 | // the same key returns the same result. | |
96 | // | |
97 | // Use context values only for request-scoped data that transits | |
98 | // processes and API boundaries, not for passing optional parameters to | |
99 | // functions. | |
100 | // | |
101 | // A key identifies a specific value in a Context. Functions that wish | |
102 | // to store values in Context typically allocate a key in a global | |
103 | // variable then use that key as the argument to context.WithValue and | |
104 | // Context.Value. A key can be any type that supports equality; | |
105 | // packages should define keys as an unexported type to avoid | |
106 | // collisions. | |
107 | // | |
108 | // Packages that define a Context key should provide type-safe accessors | |
109 | // for the values stores using that key: | |
110 | // | |
111 | // // Package user defines a User type that's stored in Contexts. | |
112 | // package user | |
113 | // | |
114 | // import "golang.org/x/net/context" | |
115 | // | |
116 | // // User is the type of value stored in the Contexts. | |
117 | // type User struct {...} | |
118 | // | |
119 | // // key is an unexported type for keys defined in this package. | |
120 | // // This prevents collisions with keys defined in other packages. | |
121 | // type key int | |
122 | // | |
123 | // // userKey is the key for user.User values in Contexts. It is | |
124 | // // unexported; clients use user.NewContext and user.FromContext | |
125 | // // instead of using this key directly. | |
126 | // var userKey key = 0 | |
127 | // | |
128 | // // NewContext returns a new Context that carries value u. | |
129 | // func NewContext(ctx context.Context, u *User) context.Context { | |
130 | // return context.WithValue(ctx, userKey, u) | |
131 | // } | |
132 | // | |
133 | // // FromContext returns the User value stored in ctx, if any. | |
134 | // func FromContext(ctx context.Context) (*User, bool) { | |
135 | // u, ok := ctx.Value(userKey).(*User) | |
136 | // return u, ok | |
137 | // } | |
138 | Value(key interface{}) interface{} | |
139 | } | |
140 | ||
141 | // Canceled is the error returned by Context.Err when the context is canceled. | |
142 | var Canceled = errors.New("context canceled") | |
143 | ||
144 | // DeadlineExceeded is the error returned by Context.Err when the context's | |
145 | // deadline passes. | |
146 | var DeadlineExceeded = errors.New("context deadline exceeded") | |
147 | ||
148 | // An emptyCtx is never canceled, has no values, and has no deadline. It is not | |
149 | // struct{}, since vars of this type must have distinct addresses. | |
150 | type emptyCtx int | |
151 | ||
152 | func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { | |
153 | return | |
154 | } | |
155 | ||
156 | func (*emptyCtx) Done() <-chan struct{} { | |
157 | return nil | |
158 | } | |
159 | ||
160 | func (*emptyCtx) Err() error { | |
161 | return nil | |
162 | } | |
163 | ||
164 | func (*emptyCtx) Value(key interface{}) interface{} { | |
165 | return nil | |
166 | } | |
167 | ||
168 | func (e *emptyCtx) String() string { | |
169 | switch e { | |
170 | case background: | |
171 | return "context.Background" | |
172 | case todo: | |
173 | return "context.TODO" | |
174 | } | |
175 | return "unknown empty Context" | |
176 | } | |
177 | ||
178 | var ( | |
179 | background = new(emptyCtx) | |
180 | todo = new(emptyCtx) | |
181 | ) | |
182 | ||
183 | // Background returns a non-nil, empty Context. It is never canceled, has no | |
184 | // values, and has no deadline. It is typically used by the main function, | |
185 | // initialization, and tests, and as the top-level Context for incoming | |
186 | // requests. | |
187 | func Background() Context { | |
188 | return background | |
189 | } | |
190 | ||
191 | // TODO returns a non-nil, empty Context. Code should use context.TODO when | |
192 | // it's unclear which Context to use or it is not yet available (because the | |
193 | // surrounding function has not yet been extended to accept a Context | |
194 | // parameter). TODO is recognized by static analysis tools that determine | |
195 | // whether Contexts are propagated correctly in a program. | |
196 | func TODO() Context { | |
197 | return todo | |
198 | } | |
199 | ||
200 | // A CancelFunc tells an operation to abandon its work. | |
201 | // A CancelFunc does not wait for the work to stop. | |
202 | // After the first call, subsequent calls to a CancelFunc do nothing. | |
203 | type CancelFunc func() | |
204 | ||
205 | // WithCancel returns a copy of parent with a new Done channel. The returned | |
206 | // context's Done channel is closed when the returned cancel function is called | |
207 | // or when the parent context's Done channel is closed, whichever happens first. | |
208 | // | |
209 | // Canceling this context releases resources associated with it, so code should | |
210 | // call cancel as soon as the operations running in this Context complete. | |
211 | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { | |
212 | c := newCancelCtx(parent) | |
213 | propagateCancel(parent, c) | |
214 | return c, func() { c.cancel(true, Canceled) } | |
215 | } | |
216 | ||
217 | // newCancelCtx returns an initialized cancelCtx. | |
218 | func newCancelCtx(parent Context) *cancelCtx { | |
219 | return &cancelCtx{ | |
220 | Context: parent, | |
221 | done: make(chan struct{}), | |
222 | } | |
223 | } | |
224 | ||
225 | // propagateCancel arranges for child to be canceled when parent is. | |
226 | func propagateCancel(parent Context, child canceler) { | |
227 | if parent.Done() == nil { | |
228 | return // parent is never canceled | |
229 | } | |
230 | if p, ok := parentCancelCtx(parent); ok { | |
231 | p.mu.Lock() | |
232 | if p.err != nil { | |
233 | // parent has already been canceled | |
234 | child.cancel(false, p.err) | |
235 | } else { | |
236 | if p.children == nil { | |
237 | p.children = make(map[canceler]bool) | |
238 | } | |
239 | p.children[child] = true | |
240 | } | |
241 | p.mu.Unlock() | |
242 | } else { | |
243 | go func() { | |
244 | select { | |
245 | case <-parent.Done(): | |
246 | child.cancel(false, parent.Err()) | |
247 | case <-child.Done(): | |
248 | } | |
249 | }() | |
250 | } | |
251 | } | |
252 | ||
253 | // parentCancelCtx follows a chain of parent references until it finds a | |
254 | // *cancelCtx. This function understands how each of the concrete types in this | |
255 | // package represents its parent. | |
256 | func parentCancelCtx(parent Context) (*cancelCtx, bool) { | |
257 | for { | |
258 | switch c := parent.(type) { | |
259 | case *cancelCtx: | |
260 | return c, true | |
261 | case *timerCtx: | |
262 | return c.cancelCtx, true | |
263 | case *valueCtx: | |
264 | parent = c.Context | |
265 | default: | |
266 | return nil, false | |
267 | } | |
268 | } | |
269 | } | |
270 | ||
271 | // removeChild removes a context from its parent. | |
272 | func removeChild(parent Context, child canceler) { | |
273 | p, ok := parentCancelCtx(parent) | |
274 | if !ok { | |
275 | return | |
276 | } | |
277 | p.mu.Lock() | |
278 | if p.children != nil { | |
279 | delete(p.children, child) | |
280 | } | |
281 | p.mu.Unlock() | |
282 | } | |
283 | ||
284 | // A canceler is a context type that can be canceled directly. The | |
285 | // implementations are *cancelCtx and *timerCtx. | |
286 | type canceler interface { | |
287 | cancel(removeFromParent bool, err error) | |
288 | Done() <-chan struct{} | |
289 | } | |
290 | ||
291 | // A cancelCtx can be canceled. When canceled, it also cancels any children | |
292 | // that implement canceler. | |
293 | type cancelCtx struct { | |
294 | Context | |
295 | ||
296 | done chan struct{} // closed by the first cancel call. | |
297 | ||
298 | mu sync.Mutex | |
299 | children map[canceler]bool // set to nil by the first cancel call | |
300 | err error // set to non-nil by the first cancel call | |
301 | } | |
302 | ||
303 | func (c *cancelCtx) Done() <-chan struct{} { | |
304 | return c.done | |
305 | } | |
306 | ||
307 | func (c *cancelCtx) Err() error { | |
308 | c.mu.Lock() | |
309 | defer c.mu.Unlock() | |
310 | return c.err | |
311 | } | |
312 | ||
313 | func (c *cancelCtx) String() string { | |
314 | return fmt.Sprintf("%v.WithCancel", c.Context) | |
315 | } | |
316 | ||
317 | // cancel closes c.done, cancels each of c's children, and, if | |
318 | // removeFromParent is true, removes c from its parent's children. | |
319 | func (c *cancelCtx) cancel(removeFromParent bool, err error) { | |
320 | if err == nil { | |
321 | panic("context: internal error: missing cancel error") | |
322 | } | |
323 | c.mu.Lock() | |
324 | if c.err != nil { | |
325 | c.mu.Unlock() | |
326 | return // already canceled | |
327 | } | |
328 | c.err = err | |
329 | close(c.done) | |
330 | for child := range c.children { | |
331 | // NOTE: acquiring the child's lock while holding parent's lock. | |
332 | child.cancel(false, err) | |
333 | } | |
334 | c.children = nil | |
335 | c.mu.Unlock() | |
336 | ||
337 | if removeFromParent { | |
338 | removeChild(c.Context, c) | |
339 | } | |
340 | } | |
341 | ||
342 | // WithDeadline returns a copy of the parent context with the deadline adjusted | |
343 | // to be no later than d. If the parent's deadline is already earlier than d, | |
344 | // WithDeadline(parent, d) is semantically equivalent to parent. The returned | |
345 | // context's Done channel is closed when the deadline expires, when the returned | |
346 | // cancel function is called, or when the parent context's Done channel is | |
347 | // closed, whichever happens first. | |
348 | // | |
349 | // Canceling this context releases resources associated with it, so code should | |
350 | // call cancel as soon as the operations running in this Context complete. | |
351 | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { | |
352 | if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { | |
353 | // The current deadline is already sooner than the new one. | |
354 | return WithCancel(parent) | |
355 | } | |
356 | c := &timerCtx{ | |
357 | cancelCtx: newCancelCtx(parent), | |
358 | deadline: deadline, | |
359 | } | |
360 | propagateCancel(parent, c) | |
361 | d := deadline.Sub(time.Now()) | |
362 | if d <= 0 { | |
363 | c.cancel(true, DeadlineExceeded) // deadline has already passed | |
364 | return c, func() { c.cancel(true, Canceled) } | |
365 | } | |
366 | c.mu.Lock() | |
367 | defer c.mu.Unlock() | |
368 | if c.err == nil { | |
369 | c.timer = time.AfterFunc(d, func() { | |
370 | c.cancel(true, DeadlineExceeded) | |
371 | }) | |
372 | } | |
373 | return c, func() { c.cancel(true, Canceled) } | |
374 | } | |
375 | ||
376 | // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to | |
377 | // implement Done and Err. It implements cancel by stopping its timer then | |
378 | // delegating to cancelCtx.cancel. | |
379 | type timerCtx struct { | |
380 | *cancelCtx | |
381 | timer *time.Timer // Under cancelCtx.mu. | |
382 | ||
383 | deadline time.Time | |
384 | } | |
385 | ||
386 | func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { | |
387 | return c.deadline, true | |
388 | } | |
389 | ||
390 | func (c *timerCtx) String() string { | |
391 | return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) | |
392 | } | |
393 | ||
394 | func (c *timerCtx) cancel(removeFromParent bool, err error) { | |
395 | c.cancelCtx.cancel(false, err) | |
396 | if removeFromParent { | |
397 | // Remove this timerCtx from its parent cancelCtx's children. | |
398 | removeChild(c.cancelCtx.Context, c) | |
399 | } | |
400 | c.mu.Lock() | |
401 | if c.timer != nil { | |
402 | c.timer.Stop() | |
403 | c.timer = nil | |
404 | } | |
405 | c.mu.Unlock() | |
406 | } | |
407 | ||
408 | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). | |
409 | // | |
410 | // Canceling this context releases resources associated with it, so code should | |
411 | // call cancel as soon as the operations running in this Context complete: | |
412 | // | |
413 | // func slowOperationWithTimeout(ctx context.Context) (Result, error) { | |
414 | // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) | |
415 | // defer cancel() // releases resources if slowOperation completes before timeout elapses | |
416 | // return slowOperation(ctx) | |
417 | // } | |
418 | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { | |
419 | return WithDeadline(parent, time.Now().Add(timeout)) | |
420 | } | |
421 | ||
422 | // WithValue returns a copy of parent in which the value associated with key is | |
423 | // val. | |
424 | // | |
425 | // Use context Values only for request-scoped data that transits processes and | |
426 | // APIs, not for passing optional parameters to functions. | |
427 | func WithValue(parent Context, key interface{}, val interface{}) Context { | |
428 | return &valueCtx{parent, key, val} | |
429 | } | |
430 | ||
431 | // A valueCtx carries a key-value pair. It implements Value for that key and | |
432 | // delegates all other calls to the embedded Context. | |
433 | type valueCtx struct { | |
434 | Context | |
435 | key, val interface{} | |
436 | } | |
437 | ||
438 | func (c *valueCtx) String() string { | |
439 | return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) | |
440 | } | |
441 | ||
442 | func (c *valueCtx) Value(key interface{}) interface{} { | |
443 | if c.key == key { | |
444 | return c.val | |
445 | } | |
446 | return c.Context.Value(key) | |
447 | } |