Source file src/context/context.go
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 // cancellation 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 10 // calls to servers should accept a Context. The chain of function 11 // calls between them must propagate the Context, optionally replacing 12 // it with a derived Context created using WithCancel, WithDeadline, 13 // WithTimeout, or WithValue. When a Context is canceled, all 14 // Contexts derived from it are also canceled. 15 // 16 // The WithCancel, WithDeadline, and WithTimeout functions take a 17 // Context (the parent) and return a derived Context (the child) and a 18 // CancelFunc. Calling the CancelFunc cancels the child and its 19 // children, removes the parent's reference to the child, and stops 20 // any associated timers. Failing to call the CancelFunc leaks the 21 // child and its children until the parent is canceled or the timer 22 // fires. The go vet tool checks that CancelFuncs are used on all 23 // control-flow paths. 24 // 25 // Programs that use Contexts should follow these rules to keep interfaces 26 // consistent across packages and enable static analysis tools to check context 27 // propagation: 28 // 29 // Do not store Contexts inside a struct type; instead, pass a Context 30 // explicitly to each function that needs it. The Context should be the first 31 // parameter, typically named ctx: 32 // 33 // func DoSomething(ctx context.Context, arg Arg) error { 34 // // ... use ctx ... 35 // } 36 // 37 // Do not pass a nil Context, even if a function permits it. Pass context.TODO 38 // if you are unsure about which Context to use. 39 // 40 // Use context Values only for request-scoped data that transits processes and 41 // APIs, not for passing optional parameters to functions. 42 // 43 // The same Context may be passed to functions running in different goroutines; 44 // Contexts are safe for simultaneous use by multiple goroutines. 45 // 46 // See https://blog.golang.org/context for example code for a server that uses 47 // Contexts. 48 package context 49 50 import ( 51 "errors" 52 "internal/reflectlite" 53 "sync" 54 "sync/atomic" 55 "time" 56 ) 57 58 // A Context carries a deadline, a cancellation signal, and other values across 59 // API boundaries. 60 // 61 // Context's methods may be called by multiple goroutines simultaneously. 62 type Context interface { 63 // Deadline returns the time when work done on behalf of this context 64 // should be canceled. Deadline returns ok==false when no deadline is 65 // set. Successive calls to Deadline return the same results. 66 Deadline() (deadline time.Time, ok bool) 67 68 // Done returns a channel that's closed when work done on behalf of this 69 // context should be canceled. Done may return nil if this context can 70 // never be canceled. Successive calls to Done return the same value. 71 // The close of the Done channel may happen asynchronously, 72 // after the cancel function returns. 73 // 74 // WithCancel arranges for Done to be closed when cancel is called; 75 // WithDeadline arranges for Done to be closed when the deadline 76 // expires; WithTimeout arranges for Done to be closed when the timeout 77 // elapses. 78 // 79 // Done is provided for use in select statements: 80 // 81 // // Stream generates values with DoSomething and sends them to out 82 // // until DoSomething returns an error or ctx.Done is closed. 83 // func Stream(ctx context.Context, out chan<- Value) error { 84 // for { 85 // v, err := DoSomething(ctx) 86 // if err != nil { 87 // return err 88 // } 89 // select { 90 // case <-ctx.Done(): 91 // return ctx.Err() 92 // case out <- v: 93 // } 94 // } 95 // } 96 // 97 // See https://blog.golang.org/pipelines for more examples of how to use 98 // a Done channel for cancellation. 99 Done() <-chan struct{} 100 101 // If Done is not yet closed, Err returns nil. 102 // If Done is closed, Err returns a non-nil error explaining why: 103 // Canceled if the context was canceled 104 // or DeadlineExceeded if the context's deadline passed. 105 // After Err returns a non-nil error, successive calls to Err return the same error. 106 Err() error 107 108 // Value returns the value associated with this context for key, or nil 109 // if no value is associated with key. Successive calls to Value with 110 // the same key returns the same result. 111 // 112 // Use context values only for request-scoped data that transits 113 // processes and API boundaries, not for passing optional parameters to 114 // functions. 115 // 116 // A key identifies a specific value in a Context. Functions that wish 117 // to store values in Context typically allocate a key in a global 118 // variable then use that key as the argument to context.WithValue and 119 // Context.Value. A key can be any type that supports equality; 120 // packages should define keys as an unexported type to avoid 121 // collisions. 122 // 123 // Packages that define a Context key should provide type-safe accessors 124 // for the values stored using that key: 125 // 126 // // Package user defines a User type that's stored in Contexts. 127 // package user 128 // 129 // import "context" 130 // 131 // // User is the type of value stored in the Contexts. 132 // type User struct {...} 133 // 134 // // key is an unexported type for keys defined in this package. 135 // // This prevents collisions with keys defined in other packages. 136 // type key int 137 // 138 // // userKey is the key for user.User values in Contexts. It is 139 // // unexported; clients use user.NewContext and user.FromContext 140 // // instead of using this key directly. 141 // var userKey key 142 // 143 // // NewContext returns a new Context that carries value u. 144 // func NewContext(ctx context.Context, u *User) context.Context { 145 // return context.WithValue(ctx, userKey, u) 146 // } 147 // 148 // // FromContext returns the User value stored in ctx, if any. 149 // func FromContext(ctx context.Context) (*User, bool) { 150 // u, ok := ctx.Value(userKey).(*User) 151 // return u, ok 152 // } 153 Value(key any) any 154 } 155 156 // Canceled is the error returned by Context.Err when the context is canceled. 157 var Canceled = errors.New("context canceled") 158 159 // DeadlineExceeded is the error returned by Context.Err when the context's 160 // deadline passes. 161 var DeadlineExceeded error = deadlineExceededError{} 162 163 type deadlineExceededError struct{} 164 165 func (deadlineExceededError) Error() string { return "context deadline exceeded" } 166 func (deadlineExceededError) Timeout() bool { return true } 167 func (deadlineExceededError) Temporary() bool { return true } 168 169 // An emptyCtx is never canceled, has no values, and has no deadline. It is not 170 // struct{}, since vars of this type must have distinct addresses. 171 type emptyCtx int 172 173 func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { 174 return 175 } 176 177 func (*emptyCtx) Done() <-chan struct{} { 178 return nil 179 } 180 181 func (*emptyCtx) Err() error { 182 return nil 183 } 184 185 func (*emptyCtx) Value(key any) any { 186 return nil 187 } 188 189 func (e *emptyCtx) String() string { 190 switch e { 191 case background: 192 return "context.Background" 193 case todo: 194 return "context.TODO" 195 } 196 return "unknown empty Context" 197 } 198 199 var ( 200 background = new(emptyCtx) 201 todo = new(emptyCtx) 202 ) 203 204 // Background returns a non-nil, empty Context. It is never canceled, has no 205 // values, and has no deadline. It is typically used by the main function, 206 // initialization, and tests, and as the top-level Context for incoming 207 // requests. 208 func Background() Context { 209 return background 210 } 211 212 // TODO returns a non-nil, empty Context. Code should use context.TODO when 213 // it's unclear which Context to use or it is not yet available (because the 214 // surrounding function has not yet been extended to accept a Context 215 // parameter). 216 func TODO() Context { 217 return todo 218 } 219 220 // A CancelFunc tells an operation to abandon its work. 221 // A CancelFunc does not wait for the work to stop. 222 // A CancelFunc may be called by multiple goroutines simultaneously. 223 // After the first call, subsequent calls to a CancelFunc do nothing. 224 type CancelFunc func() 225 226 // WithCancel returns a copy of parent with a new Done channel. The returned 227 // context's Done channel is closed when the returned cancel function is called 228 // or when the parent context's Done channel is closed, whichever happens first. 229 // 230 // Canceling this context releases resources associated with it, so code should 231 // call cancel as soon as the operations running in this Context complete. 232 func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { 233 if parent == nil { 234 panic("cannot create context from nil parent") 235 } 236 c := newCancelCtx(parent) 237 propagateCancel(parent, &c) 238 return &c, func() { c.cancel(true, Canceled) } 239 } 240 241 // newCancelCtx returns an initialized cancelCtx. 242 func newCancelCtx(parent Context) cancelCtx { 243 return cancelCtx{Context: parent} 244 } 245 246 // goroutines counts the number of goroutines ever created; for testing. 247 var goroutines int32 248 249 // propagateCancel arranges for child to be canceled when parent is. 250 func propagateCancel(parent Context, child canceler) { 251 done := parent.Done() 252 if done == nil { 253 return // parent is never canceled 254 } 255 256 select { 257 case <-done: 258 // parent is already canceled 259 child.cancel(false, parent.Err()) 260 return 261 default: 262 } 263 264 if p, ok := parentCancelCtx(parent); ok { 265 p.mu.Lock() 266 if p.err != nil { 267 // parent has already been canceled 268 child.cancel(false, p.err) 269 } else { 270 if p.children == nil { 271 p.children = make(map[canceler]struct{}) 272 } 273 p.children[child] = struct{}{} 274 } 275 p.mu.Unlock() 276 } else { 277 atomic.AddInt32(&goroutines, +1) 278 go func() { 279 select { 280 case <-parent.Done(): 281 child.cancel(false, parent.Err()) 282 case <-child.Done(): 283 } 284 }() 285 } 286 } 287 288 // &cancelCtxKey is the key that a cancelCtx returns itself for. 289 var cancelCtxKey int 290 291 // parentCancelCtx returns the underlying *cancelCtx for parent. 292 // It does this by looking up parent.Value(&cancelCtxKey) to find 293 // the innermost enclosing *cancelCtx and then checking whether 294 // parent.Done() matches that *cancelCtx. (If not, the *cancelCtx 295 // has been wrapped in a custom implementation providing a 296 // different done channel, in which case we should not bypass it.) 297 func parentCancelCtx(parent Context) (*cancelCtx, bool) { 298 done := parent.Done() 299 if done == closedchan || done == nil { 300 return nil, false 301 } 302 p, ok := parent.Value(&cancelCtxKey).(*cancelCtx) 303 if !ok { 304 return nil, false 305 } 306 pdone, _ := p.done.Load().(chan struct{}) 307 if pdone != done { 308 return nil, false 309 } 310 return p, true 311 } 312 313 // removeChild removes a context from its parent. 314 func removeChild(parent Context, child canceler) { 315 p, ok := parentCancelCtx(parent) 316 if !ok { 317 return 318 } 319 p.mu.Lock() 320 if p.children != nil { 321 delete(p.children, child) 322 } 323 p.mu.Unlock() 324 } 325 326 // A canceler is a context type that can be canceled directly. The 327 // implementations are *cancelCtx and *timerCtx. 328 type canceler interface { 329 cancel(removeFromParent bool, err error) 330 Done() <-chan struct{} 331 } 332 333 // closedchan is a reusable closed channel. 334 var closedchan = make(chan struct{}) 335 336 func init() { 337 close(closedchan) 338 } 339 340 // A cancelCtx can be canceled. When canceled, it also cancels any children 341 // that implement canceler. 342 type cancelCtx struct { 343 Context 344 345 mu sync.Mutex // protects following fields 346 done atomic.Value // of chan struct{}, created lazily, closed by first cancel call 347 children map[canceler]struct{} // set to nil by the first cancel call 348 err error // set to non-nil by the first cancel call 349 } 350 351 func (c *cancelCtx) Value(key any) any { 352 if key == &cancelCtxKey { 353 return c 354 } 355 return value(c.Context, key) 356 } 357 358 func (c *cancelCtx) Done() <-chan struct{} { 359 d := c.done.Load() 360 if d != nil { 361 return d.(chan struct{}) 362 } 363 c.mu.Lock() 364 defer c.mu.Unlock() 365 d = c.done.Load() 366 if d == nil { 367 d = make(chan struct{}) 368 c.done.Store(d) 369 } 370 return d.(chan struct{}) 371 } 372 373 func (c *cancelCtx) Err() error { 374 c.mu.Lock() 375 err := c.err 376 c.mu.Unlock() 377 return err 378 } 379 380 type stringer interface { 381 String() string 382 } 383 384 func contextName(c Context) string { 385 if s, ok := c.(stringer); ok { 386 return s.String() 387 } 388 return reflectlite.TypeOf(c).String() 389 } 390 391 func (c *cancelCtx) String() string { 392 return contextName(c.Context) + ".WithCancel" 393 } 394 395 // cancel closes c.done, cancels each of c's children, and, if 396 // removeFromParent is true, removes c from its parent's children. 397 func (c *cancelCtx) cancel(removeFromParent bool, err error) { 398 if err == nil { 399 panic("context: internal error: missing cancel error") 400 } 401 c.mu.Lock() 402 if c.err != nil { 403 c.mu.Unlock() 404 return // already canceled 405 } 406 c.err = err 407 d, _ := c.done.Load().(chan struct{}) 408 if d == nil { 409 c.done.Store(closedchan) 410 } else { 411 close(d) 412 } 413 for child := range c.children { 414 // NOTE: acquiring the child's lock while holding parent's lock. 415 child.cancel(false, err) 416 } 417 c.children = nil 418 c.mu.Unlock() 419 420 if removeFromParent { 421 removeChild(c.Context, c) 422 } 423 } 424 425 // WithDeadline returns a copy of the parent context with the deadline adjusted 426 // to be no later than d. If the parent's deadline is already earlier than d, 427 // WithDeadline(parent, d) is semantically equivalent to parent. The returned 428 // context's Done channel is closed when the deadline expires, when the returned 429 // cancel function is called, or when the parent context's Done channel is 430 // closed, whichever happens first. 431 // 432 // Canceling this context releases resources associated with it, so code should 433 // call cancel as soon as the operations running in this Context complete. 434 func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) { 435 if parent == nil { 436 panic("cannot create context from nil parent") 437 } 438 if cur, ok := parent.Deadline(); ok && cur.Before(d) { 439 // The current deadline is already sooner than the new one. 440 return WithCancel(parent) 441 } 442 c := &timerCtx{ 443 cancelCtx: newCancelCtx(parent), 444 deadline: d, 445 } 446 propagateCancel(parent, c) 447 dur := time.Until(d) 448 if dur <= 0 { 449 c.cancel(true, DeadlineExceeded) // deadline has already passed 450 return c, func() { c.cancel(false, Canceled) } 451 } 452 c.mu.Lock() 453 defer c.mu.Unlock() 454 if c.err == nil { 455 c.timer = time.AfterFunc(dur, func() { 456 c.cancel(true, DeadlineExceeded) 457 }) 458 } 459 return c, func() { c.cancel(true, Canceled) } 460 } 461 462 // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to 463 // implement Done and Err. It implements cancel by stopping its timer then 464 // delegating to cancelCtx.cancel. 465 type timerCtx struct { 466 cancelCtx 467 timer *time.Timer // Under cancelCtx.mu. 468 469 deadline time.Time 470 } 471 472 func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { 473 return c.deadline, true 474 } 475 476 func (c *timerCtx) String() string { 477 return contextName(c.cancelCtx.Context) + ".WithDeadline(" + 478 c.deadline.String() + " [" + 479 time.Until(c.deadline).String() + "])" 480 } 481 482 func (c *timerCtx) cancel(removeFromParent bool, err error) { 483 c.cancelCtx.cancel(false, err) 484 if removeFromParent { 485 // Remove this timerCtx from its parent cancelCtx's children. 486 removeChild(c.cancelCtx.Context, c) 487 } 488 c.mu.Lock() 489 if c.timer != nil { 490 c.timer.Stop() 491 c.timer = nil 492 } 493 c.mu.Unlock() 494 } 495 496 // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). 497 // 498 // Canceling this context releases resources associated with it, so code should 499 // call cancel as soon as the operations running in this Context complete: 500 // 501 // func slowOperationWithTimeout(ctx context.Context) (Result, error) { 502 // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 503 // defer cancel() // releases resources if slowOperation completes before timeout elapses 504 // return slowOperation(ctx) 505 // } 506 func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { 507 return WithDeadline(parent, time.Now().Add(timeout)) 508 } 509 510 // WithValue returns a copy of parent in which the value associated with key is 511 // val. 512 // 513 // Use context Values only for request-scoped data that transits processes and 514 // APIs, not for passing optional parameters to functions. 515 // 516 // The provided key must be comparable and should not be of type 517 // string or any other built-in type to avoid collisions between 518 // packages using context. Users of WithValue should define their own 519 // types for keys. To avoid allocating when assigning to an 520 // interface{}, context keys often have concrete type 521 // struct{}. Alternatively, exported context key variables' static 522 // type should be a pointer or interface. 523 func WithValue(parent Context, key, val any) Context { 524 if parent == nil { 525 panic("cannot create context from nil parent") 526 } 527 if key == nil { 528 panic("nil key") 529 } 530 if !reflectlite.TypeOf(key).Comparable() { 531 panic("key is not comparable") 532 } 533 return &valueCtx{parent, key, val} 534 } 535 536 // A valueCtx carries a key-value pair. It implements Value for that key and 537 // delegates all other calls to the embedded Context. 538 type valueCtx struct { 539 Context 540 key, val any 541 } 542 543 // stringify tries a bit to stringify v, without using fmt, since we don't 544 // want context depending on the unicode tables. This is only used by 545 // *valueCtx.String(). 546 func stringify(v any) string { 547 switch s := v.(type) { 548 case stringer: 549 return s.String() 550 case string: 551 return s 552 } 553 return "<not Stringer>" 554 } 555 556 func (c *valueCtx) String() string { 557 return contextName(c.Context) + ".WithValue(type " + 558 reflectlite.TypeOf(c.key).String() + 559 ", val " + stringify(c.val) + ")" 560 } 561 562 func (c *valueCtx) Value(key any) any { 563 if c.key == key { 564 return c.val 565 } 566 return value(c.Context, key) 567 } 568 569 func value(c Context, key any) any { 570 for { 571 switch ctx := c.(type) { 572 case *valueCtx: 573 if key == ctx.key { 574 return ctx.val 575 } 576 c = ctx.Context 577 case *cancelCtx: 578 if key == &cancelCtxKey { 579 return c 580 } 581 c = ctx.Context 582 case *timerCtx: 583 if key == &cancelCtxKey { 584 return &ctx.cancelCtx 585 } 586 c = ctx.Context 587 case *emptyCtx: 588 return nil 589 default: 590 return c.Value(key) 591 } 592 } 593 } 594