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