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// The [WithCancelCause] function returns a [CancelCauseFunc], which
26// takes an error and records it as the cancellation cause. Calling
27// [Cause] on the canceled context or any of its children retrieves
28// the cause. If no cause is specified, Cause(ctx) returns the same
29// value as ctx.Err().
30//
31// Programs that use Contexts should follow these rules to keep interfaces
32// consistent across packages and enable static analysis tools to check context
33// propagation:
34//
35// Do not store Contexts inside a struct type; instead, pass a Context
36// explicitly to each function that needs it. The Context should be the first
37// parameter, typically named ctx:
38//
39//	func DoSomething(ctx context.Context, arg Arg) error {
40//		// ... use ctx ...
41//	}
42//
43// Do not pass a nil [Context], even if a function permits it. Pass [context.TODO]
44// if you are unsure about which Context to use.
45//
46// Use context Values only for request-scoped data that transits processes and
47// APIs, not for passing optional parameters to functions.
48//
49// The same Context may be passed to functions running in different goroutines;
50// Contexts are safe for simultaneous use by multiple goroutines.
51//
52// See https://blog.golang.org/context for example code for a server that uses
53// Contexts.
54package context
55
56import (
57	"errors"
58	"internal/reflectlite"
59	"sync"
60	"sync/atomic"
61	"time"
62)
63
64// A Context carries a deadline, a cancellation signal, and other values across
65// API boundaries.
66//
67// Context's methods may be called by multiple goroutines simultaneously.
68type Context interface {
69	// Deadline returns the time when work done on behalf of this context
70	// should be canceled. Deadline returns ok==false when no deadline is
71	// set. Successive calls to Deadline return the same results.
72	Deadline() (deadline time.Time, ok bool)
73
74	// Done returns a channel that's closed when work done on behalf of this
75	// context should be canceled. Done may return nil if this context can
76	// never be canceled. Successive calls to Done return the same value.
77	// The close of the Done channel may happen asynchronously,
78	// after the cancel function returns.
79	//
80	// WithCancel arranges for Done to be closed when cancel is called;
81	// WithDeadline arranges for Done to be closed when the deadline
82	// expires; WithTimeout arranges for Done to be closed when the timeout
83	// elapses.
84	//
85	// Done is provided for use in select statements:
86	//
87	//  // Stream generates values with DoSomething and sends them to out
88	//  // until DoSomething returns an error or ctx.Done is closed.
89	//  func Stream(ctx context.Context, out chan<- Value) error {
90	//  	for {
91	//  		v, err := DoSomething(ctx)
92	//  		if err != nil {
93	//  			return err
94	//  		}
95	//  		select {
96	//  		case <-ctx.Done():
97	//  			return ctx.Err()
98	//  		case out <- v:
99	//  		}
100	//  	}
101	//  }
102	//
103	// See https://blog.golang.org/pipelines for more examples of how to use
104	// a Done channel for cancellation.
105	Done() <-chan struct{}
106
107	// If Done is not yet closed, Err returns nil.
108	// If Done is closed, Err returns a non-nil error explaining why:
109	// Canceled if the context was canceled
110	// or DeadlineExceeded if the context's deadline passed.
111	// After Err returns a non-nil error, successive calls to Err return the same error.
112	Err() error
113
114	// Value returns the value associated with this context for key, or nil
115	// if no value is associated with key. Successive calls to Value with
116	// the same key returns the same result.
117	//
118	// Use context values only for request-scoped data that transits
119	// processes and API boundaries, not for passing optional parameters to
120	// functions.
121	//
122	// A key identifies a specific value in a Context. Functions that wish
123	// to store values in Context typically allocate a key in a global
124	// variable then use that key as the argument to context.WithValue and
125	// Context.Value. A key can be any type that supports equality;
126	// packages should define keys as an unexported type to avoid
127	// collisions.
128	//
129	// Packages that define a Context key should provide type-safe accessors
130	// for the values stored using that key:
131	//
132	// 	// Package user defines a User type that's stored in Contexts.
133	// 	package user
134	//
135	// 	import "context"
136	//
137	// 	// User is the type of value stored in the Contexts.
138	// 	type User struct {...}
139	//
140	// 	// key is an unexported type for keys defined in this package.
141	// 	// This prevents collisions with keys defined in other packages.
142	// 	type key int
143	//
144	// 	// userKey is the key for user.User values in Contexts. It is
145	// 	// unexported; clients use user.NewContext and user.FromContext
146	// 	// instead of using this key directly.
147	// 	var userKey key
148	//
149	// 	// NewContext returns a new Context that carries value u.
150	// 	func NewContext(ctx context.Context, u *User) context.Context {
151	// 		return context.WithValue(ctx, userKey, u)
152	// 	}
153	//
154	// 	// FromContext returns the User value stored in ctx, if any.
155	// 	func FromContext(ctx context.Context) (*User, bool) {
156	// 		u, ok := ctx.Value(userKey).(*User)
157	// 		return u, ok
158	// 	}
159	Value(key any) any
160}
161
162// Canceled is the error returned by [Context.Err] when the context is canceled.
163var Canceled = errors.New("context canceled")
164
165// DeadlineExceeded is the error returned by [Context.Err] when the context's
166// deadline passes.
167var DeadlineExceeded error = deadlineExceededError{}
168
169type deadlineExceededError struct{}
170
171func (deadlineExceededError) Error() string   { return "context deadline exceeded" }
172func (deadlineExceededError) Timeout() bool   { return true }
173func (deadlineExceededError) Temporary() bool { return true }
174
175// An emptyCtx is never canceled, has no values, and has no deadline.
176// It is the common base of backgroundCtx and todoCtx.
177type emptyCtx struct{}
178
179func (emptyCtx) Deadline() (deadline time.Time, ok bool) {
180	return
181}
182
183func (emptyCtx) Done() <-chan struct{} {
184	return nil
185}
186
187func (emptyCtx) Err() error {
188	return nil
189}
190
191func (emptyCtx) Value(key any) any {
192	return nil
193}
194
195type backgroundCtx struct{ emptyCtx }
196
197func (backgroundCtx) String() string {
198	return "context.Background"
199}
200
201type todoCtx struct{ emptyCtx }
202
203func (todoCtx) String() string {
204	return "context.TODO"
205}
206
207// Background returns a non-nil, empty [Context]. It is never canceled, has no
208// values, and has no deadline. It is typically used by the main function,
209// initialization, and tests, and as the top-level Context for incoming
210// requests.
211func Background() Context {
212	return backgroundCtx{}
213}
214
215// TODO returns a non-nil, empty [Context]. Code should use context.TODO when
216// it's unclear which Context to use or it is not yet available (because the
217// surrounding function has not yet been extended to accept a Context
218// parameter).
219func TODO() Context {
220	return todoCtx{}
221}
222
223// A CancelFunc tells an operation to abandon its work.
224// A CancelFunc does not wait for the work to stop.
225// A CancelFunc may be called by multiple goroutines simultaneously.
226// After the first call, subsequent calls to a CancelFunc do nothing.
227type CancelFunc func()
228
229// WithCancel returns a copy of parent with a new Done channel. The returned
230// context's Done channel is closed when the returned cancel function is called
231// or when the parent context's Done channel is closed, whichever happens first.
232//
233// Canceling this context releases resources associated with it, so code should
234// call cancel as soon as the operations running in this [Context] complete.
235func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
236	c := withCancel(parent)
237	return c, func() { c.cancel(true, Canceled, nil) }
238}
239
240// A CancelCauseFunc behaves like a [CancelFunc] but additionally sets the cancellation cause.
241// This cause can be retrieved by calling [Cause] on the canceled Context or on
242// any of its derived Contexts.
243//
244// If the context has already been canceled, CancelCauseFunc does not set the cause.
245// For example, if childContext is derived from parentContext:
246//   - if parentContext is canceled with cause1 before childContext is canceled with cause2,
247//     then Cause(parentContext) == Cause(childContext) == cause1
248//   - if childContext is canceled with cause2 before parentContext is canceled with cause1,
249//     then Cause(parentContext) == cause1 and Cause(childContext) == cause2
250type CancelCauseFunc func(cause error)
251
252// WithCancelCause behaves like [WithCancel] but returns a [CancelCauseFunc] instead of a [CancelFunc].
253// Calling cancel with a non-nil error (the "cause") records that error in ctx;
254// it can then be retrieved using Cause(ctx).
255// Calling cancel with nil sets the cause to Canceled.
256//
257// Example use:
258//
259//	ctx, cancel := context.WithCancelCause(parent)
260//	cancel(myError)
261//	ctx.Err() // returns context.Canceled
262//	context.Cause(ctx) // returns myError
263func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc) {
264	c := withCancel(parent)
265	return c, func(cause error) { c.cancel(true, Canceled, cause) }
266}
267
268func withCancel(parent Context) *cancelCtx {
269	if parent == nil {
270		panic("cannot create context from nil parent")
271	}
272	c := &cancelCtx{}
273	c.propagateCancel(parent, c)
274	return c
275}
276
277// Cause returns a non-nil error explaining why c was canceled.
278// The first cancellation of c or one of its parents sets the cause.
279// If that cancellation happened via a call to CancelCauseFunc(err),
280// then [Cause] returns err.
281// Otherwise Cause(c) returns the same value as c.Err().
282// Cause returns nil if c has not been canceled yet.
283func Cause(c Context) error {
284	if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok {
285		cc.mu.Lock()
286		defer cc.mu.Unlock()
287		return cc.cause
288	}
289	// There is no cancelCtxKey value, so we know that c is
290	// not a descendant of some Context created by WithCancelCause.
291	// Therefore, there is no specific cause to return.
292	// If this is not one of the standard Context types,
293	// it might still have an error even though it won't have a cause.
294	return c.Err()
295}
296
297// AfterFunc arranges to call f in its own goroutine after ctx is done
298// (canceled or timed out).
299// If ctx is already done, AfterFunc calls f immediately in its own goroutine.
300//
301// Multiple calls to AfterFunc on a context operate independently;
302// one does not replace another.
303//
304// Calling the returned stop function stops the association of ctx with f.
305// It returns true if the call stopped f from being run.
306// If stop returns false,
307// either the context is done and f has been started in its own goroutine;
308// or f was already stopped.
309// The stop function does not wait for f to complete before returning.
310// If the caller needs to know whether f is completed,
311// it must coordinate with f explicitly.
312//
313// If ctx has a "AfterFunc(func()) func() bool" method,
314// AfterFunc will use it to schedule the call.
315func AfterFunc(ctx Context, f func()) (stop func() bool) {
316	a := &afterFuncCtx{
317		f: f,
318	}
319	a.cancelCtx.propagateCancel(ctx, a)
320	return func() bool {
321		stopped := false
322		a.once.Do(func() {
323			stopped = true
324		})
325		if stopped {
326			a.cancel(true, Canceled, nil)
327		}
328		return stopped
329	}
330}
331
332type afterFuncer interface {
333	AfterFunc(func()) func() bool
334}
335
336type afterFuncCtx struct {
337	cancelCtx
338	once sync.Once // either starts running f or stops f from running
339	f    func()
340}
341
342func (a *afterFuncCtx) cancel(removeFromParent bool, err, cause error) {
343	a.cancelCtx.cancel(false, err, cause)
344	if removeFromParent {
345		removeChild(a.Context, a)
346	}
347	a.once.Do(func() {
348		go a.f()
349	})
350}
351
352// A stopCtx is used as the parent context of a cancelCtx when
353// an AfterFunc has been registered with the parent.
354// It holds the stop function used to unregister the AfterFunc.
355type stopCtx struct {
356	Context
357	stop func() bool
358}
359
360// goroutines counts the number of goroutines ever created; for testing.
361var goroutines atomic.Int32
362
363// &cancelCtxKey is the key that a cancelCtx returns itself for.
364var cancelCtxKey int
365
366// parentCancelCtx returns the underlying *cancelCtx for parent.
367// It does this by looking up parent.Value(&cancelCtxKey) to find
368// the innermost enclosing *cancelCtx and then checking whether
369// parent.Done() matches that *cancelCtx. (If not, the *cancelCtx
370// has been wrapped in a custom implementation providing a
371// different done channel, in which case we should not bypass it.)
372func parentCancelCtx(parent Context) (*cancelCtx, bool) {
373	done := parent.Done()
374	if done == closedchan || done == nil {
375		return nil, false
376	}
377	p, ok := parent.Value(&cancelCtxKey).(*cancelCtx)
378	if !ok {
379		return nil, false
380	}
381	pdone, _ := p.done.Load().(chan struct{})
382	if pdone != done {
383		return nil, false
384	}
385	return p, true
386}
387
388// removeChild removes a context from its parent.
389func removeChild(parent Context, child canceler) {
390	if s, ok := parent.(stopCtx); ok {
391		s.stop()
392		return
393	}
394	p, ok := parentCancelCtx(parent)
395	if !ok {
396		return
397	}
398	p.mu.Lock()
399	if p.children != nil {
400		delete(p.children, child)
401	}
402	p.mu.Unlock()
403}
404
405// A canceler is a context type that can be canceled directly. The
406// implementations are *cancelCtx and *timerCtx.
407type canceler interface {
408	cancel(removeFromParent bool, err, cause error)
409	Done() <-chan struct{}
410}
411
412// closedchan is a reusable closed channel.
413var closedchan = make(chan struct{})
414
415func init() {
416	close(closedchan)
417}
418
419// A cancelCtx can be canceled. When canceled, it also cancels any children
420// that implement canceler.
421type cancelCtx struct {
422	Context
423
424	mu       sync.Mutex            // protects following fields
425	done     atomic.Value          // of chan struct{}, created lazily, closed by first cancel call
426	children map[canceler]struct{} // set to nil by the first cancel call
427	err      error                 // set to non-nil by the first cancel call
428	cause    error                 // set to non-nil by the first cancel call
429}
430
431func (c *cancelCtx) Value(key any) any {
432	if key == &cancelCtxKey {
433		return c
434	}
435	return value(c.Context, key)
436}
437
438func (c *cancelCtx) Done() <-chan struct{} {
439	d := c.done.Load()
440	if d != nil {
441		return d.(chan struct{})
442	}
443	c.mu.Lock()
444	defer c.mu.Unlock()
445	d = c.done.Load()
446	if d == nil {
447		d = make(chan struct{})
448		c.done.Store(d)
449	}
450	return d.(chan struct{})
451}
452
453func (c *cancelCtx) Err() error {
454	c.mu.Lock()
455	err := c.err
456	c.mu.Unlock()
457	return err
458}
459
460// propagateCancel arranges for child to be canceled when parent is.
461// It sets the parent context of cancelCtx.
462func (c *cancelCtx) propagateCancel(parent Context, child canceler) {
463	c.Context = parent
464
465	done := parent.Done()
466	if done == nil {
467		return // parent is never canceled
468	}
469
470	select {
471	case <-done:
472		// parent is already canceled
473		child.cancel(false, parent.Err(), Cause(parent))
474		return
475	default:
476	}
477
478	if p, ok := parentCancelCtx(parent); ok {
479		// parent is a *cancelCtx, or derives from one.
480		p.mu.Lock()
481		if p.err != nil {
482			// parent has already been canceled
483			child.cancel(false, p.err, p.cause)
484		} else {
485			if p.children == nil {
486				p.children = make(map[canceler]struct{})
487			}
488			p.children[child] = struct{}{}
489		}
490		p.mu.Unlock()
491		return
492	}
493
494	if a, ok := parent.(afterFuncer); ok {
495		// parent implements an AfterFunc method.
496		c.mu.Lock()
497		stop := a.AfterFunc(func() {
498			child.cancel(false, parent.Err(), Cause(parent))
499		})
500		c.Context = stopCtx{
501			Context: parent,
502			stop:    stop,
503		}
504		c.mu.Unlock()
505		return
506	}
507
508	goroutines.Add(1)
509	go func() {
510		select {
511		case <-parent.Done():
512			child.cancel(false, parent.Err(), Cause(parent))
513		case <-child.Done():
514		}
515	}()
516}
517
518type stringer interface {
519	String() string
520}
521
522func contextName(c Context) string {
523	if s, ok := c.(stringer); ok {
524		return s.String()
525	}
526	return reflectlite.TypeOf(c).String()
527}
528
529func (c *cancelCtx) String() string {
530	return contextName(c.Context) + ".WithCancel"
531}
532
533// cancel closes c.done, cancels each of c's children, and, if
534// removeFromParent is true, removes c from its parent's children.
535// cancel sets c.cause to cause if this is the first time c is canceled.
536func (c *cancelCtx) cancel(removeFromParent bool, err, cause error) {
537	if err == nil {
538		panic("context: internal error: missing cancel error")
539	}
540	if cause == nil {
541		cause = err
542	}
543	c.mu.Lock()
544	if c.err != nil {
545		c.mu.Unlock()
546		return // already canceled
547	}
548	c.err = err
549	c.cause = cause
550	d, _ := c.done.Load().(chan struct{})
551	if d == nil {
552		c.done.Store(closedchan)
553	} else {
554		close(d)
555	}
556	for child := range c.children {
557		// NOTE: acquiring the child's lock while holding parent's lock.
558		child.cancel(false, err, cause)
559	}
560	c.children = nil
561	c.mu.Unlock()
562
563	if removeFromParent {
564		removeChild(c.Context, c)
565	}
566}
567
568// WithoutCancel returns a copy of parent that is not canceled when parent is canceled.
569// The returned context returns no Deadline or Err, and its Done channel is nil.
570// Calling [Cause] on the returned context returns nil.
571func WithoutCancel(parent Context) Context {
572	if parent == nil {
573		panic("cannot create context from nil parent")
574	}
575	return withoutCancelCtx{parent}
576}
577
578type withoutCancelCtx struct {
579	c Context
580}
581
582func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {
583	return
584}
585
586func (withoutCancelCtx) Done() <-chan struct{} {
587	return nil
588}
589
590func (withoutCancelCtx) Err() error {
591	return nil
592}
593
594func (c withoutCancelCtx) Value(key any) any {
595	return value(c, key)
596}
597
598func (c withoutCancelCtx) String() string {
599	return contextName(c.c) + ".WithoutCancel"
600}
601
602// WithDeadline returns a copy of the parent context with the deadline adjusted
603// to be no later than d. If the parent's deadline is already earlier than d,
604// WithDeadline(parent, d) is semantically equivalent to parent. The returned
605// [Context.Done] channel is closed when the deadline expires, when the returned
606// cancel function is called, or when the parent context's Done channel is
607// closed, whichever happens first.
608//
609// Canceling this context releases resources associated with it, so code should
610// call cancel as soon as the operations running in this [Context] complete.
611func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
612	return WithDeadlineCause(parent, d, nil)
613}
614
615// WithDeadlineCause behaves like [WithDeadline] but also sets the cause of the
616// returned Context when the deadline is exceeded. The returned [CancelFunc] does
617// not set the cause.
618func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc) {
619	if parent == nil {
620		panic("cannot create context from nil parent")
621	}
622	if cur, ok := parent.Deadline(); ok && cur.Before(d) {
623		// The current deadline is already sooner than the new one.
624		return WithCancel(parent)
625	}
626	c := &timerCtx{
627		deadline: d,
628	}
629	c.cancelCtx.propagateCancel(parent, c)
630	dur := time.Until(d)
631	if dur <= 0 {
632		c.cancel(true, DeadlineExceeded, cause) // deadline has already passed
633		return c, func() { c.cancel(false, Canceled, nil) }
634	}
635	c.mu.Lock()
636	defer c.mu.Unlock()
637	if c.err == nil {
638		c.timer = time.AfterFunc(dur, func() {
639			c.cancel(true, DeadlineExceeded, cause)
640		})
641	}
642	return c, func() { c.cancel(true, Canceled, nil) }
643}
644
645// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
646// implement Done and Err. It implements cancel by stopping its timer then
647// delegating to cancelCtx.cancel.
648type timerCtx struct {
649	cancelCtx
650	timer *time.Timer // Under cancelCtx.mu.
651
652	deadline time.Time
653}
654
655func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
656	return c.deadline, true
657}
658
659func (c *timerCtx) String() string {
660	return contextName(c.cancelCtx.Context) + ".WithDeadline(" +
661		c.deadline.String() + " [" +
662		time.Until(c.deadline).String() + "])"
663}
664
665func (c *timerCtx) cancel(removeFromParent bool, err, cause error) {
666	c.cancelCtx.cancel(false, err, cause)
667	if removeFromParent {
668		// Remove this timerCtx from its parent cancelCtx's children.
669		removeChild(c.cancelCtx.Context, c)
670	}
671	c.mu.Lock()
672	if c.timer != nil {
673		c.timer.Stop()
674		c.timer = nil
675	}
676	c.mu.Unlock()
677}
678
679// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
680//
681// Canceling this context releases resources associated with it, so code should
682// call cancel as soon as the operations running in this [Context] complete:
683//
684//	func slowOperationWithTimeout(ctx context.Context) (Result, error) {
685//		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
686//		defer cancel()  // releases resources if slowOperation completes before timeout elapses
687//		return slowOperation(ctx)
688//	}
689func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
690	return WithDeadline(parent, time.Now().Add(timeout))
691}
692
693// WithTimeoutCause behaves like [WithTimeout] but also sets the cause of the
694// returned Context when the timeout expires. The returned [CancelFunc] does
695// not set the cause.
696func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc) {
697	return WithDeadlineCause(parent, time.Now().Add(timeout), cause)
698}
699
700// WithValue returns a copy of parent in which the value associated with key is
701// val.
702//
703// Use context Values only for request-scoped data that transits processes and
704// APIs, not for passing optional parameters to functions.
705//
706// The provided key must be comparable and should not be of type
707// string or any other built-in type to avoid collisions between
708// packages using context. Users of WithValue should define their own
709// types for keys. To avoid allocating when assigning to an
710// interface{}, context keys often have concrete type
711// struct{}. Alternatively, exported context key variables' static
712// type should be a pointer or interface.
713func WithValue(parent Context, key, val any) Context {
714	if parent == nil {
715		panic("cannot create context from nil parent")
716	}
717	if key == nil {
718		panic("nil key")
719	}
720	if !reflectlite.TypeOf(key).Comparable() {
721		panic("key is not comparable")
722	}
723	return &valueCtx{parent, key, val}
724}
725
726// A valueCtx carries a key-value pair. It implements Value for that key and
727// delegates all other calls to the embedded Context.
728type valueCtx struct {
729	Context
730	key, val any
731}
732
733// stringify tries a bit to stringify v, without using fmt, since we don't
734// want context depending on the unicode tables. This is only used by
735// *valueCtx.String().
736func stringify(v any) string {
737	switch s := v.(type) {
738	case stringer:
739		return s.String()
740	case string:
741		return s
742	case nil:
743		return "<nil>"
744	}
745	return reflectlite.TypeOf(v).String()
746}
747
748func (c *valueCtx) String() string {
749	return contextName(c.Context) + ".WithValue(" +
750		stringify(c.key) + ", " +
751		stringify(c.val) + ")"
752}
753
754func (c *valueCtx) Value(key any) any {
755	if c.key == key {
756		return c.val
757	}
758	return value(c.Context, key)
759}
760
761func value(c Context, key any) any {
762	for {
763		switch ctx := c.(type) {
764		case *valueCtx:
765			if key == ctx.key {
766				return ctx.val
767			}
768			c = ctx.Context
769		case *cancelCtx:
770			if key == &cancelCtxKey {
771				return c
772			}
773			c = ctx.Context
774		case withoutCancelCtx:
775			if key == &cancelCtxKey {
776				// This implements Cause(ctx) == nil
777				// when ctx is created using WithoutCancel.
778				return nil
779			}
780			c = ctx.c
781		case *timerCtx:
782			if key == &cancelCtxKey {
783				return &ctx.cancelCtx
784			}
785			c = ctx.Context
786		case backgroundCtx, todoCtx:
787			return nil
788		default:
789			return c.Value(key)
790		}
791	}
792}
793