// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build !go1.7 // +build !go1.7 package context import ( "errors" "fmt" "sync" "time" ) // An emptyCtx is never canceled, has no values, and has no deadline. It is not // struct{}, since vars of this type must have distinct addresses. type emptyCtx int func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { return } func (*emptyCtx) Done() <-chan struct{} { return nil } func (*emptyCtx) Err() error { return nil } func (*emptyCtx) Value(key interface{}) interface{} { return nil } func (e *emptyCtx) String() string { switch e { case background: return "context.Background" case todo: return "context.TODO" } return "unknown empty Context" } var ( background = new(emptyCtx) todo = new(emptyCtx) ) // Canceled is the error returned by Context.Err when the context is canceled. var Canceled = errors.New("context canceled") // DeadlineExceeded is the error returned by Context.Err when the context's // deadline passes. var DeadlineExceeded = errors.New("context deadline exceeded") // WithCancel returns a copy of parent with a new Done channel. The returned // context's Done channel is closed when the returned cancel function is called // or when the parent context's Done channel is closed, whichever happens first. // // Canceling this context releases resources associated with it, so code should // call cancel as soon as the operations running in this Context complete. func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := newCancelCtx(parent) propagateCancel(parent, c) return c, func() { c.cancel(true, Canceled) } } // newCancelCtx returns an initialized cancelCtx. func newCancelCtx(parent Context) *cancelCtx { return &cancelCtx{ Context: parent, done: make(chan struct{}), } } // propagateCancel arranges for child to be canceled when parent is. func propagateCancel(parent Context, child canceler) { if parent.Done() == nil { return // parent is never canceled } if p, ok := parentCancelCtx(parent); ok { p.mu.Lock() if p.err != nil { // parent has already been canceled child.cancel(false, p.err) } else { if p.children == nil { p.children = make(map[canceler]bool) } p.children[child] = true } p.mu.Unlock() } else { go func() { select { case <-parent.Done(): child.cancel(false, parent.Err()) case <-child.Done(): } }() } } // parentCancelCtx follows a chain of parent references until it finds a // *cancelCtx. This function understands how each of the concrete types in this // package represents its parent. func parentCancelCtx(parent Context) (*cancelCtx, bool) { for { switch c := parent.(type) { case *cancelCtx: return c, true case *timerCtx: return c.cancelCtx, true case *valueCtx: parent = c.Context default: return nil, false } } } // removeChild removes a context from its parent. func removeChild(parent Context, child canceler) { p, ok := parentCancelCtx(parent) if !ok { return } p.mu.Lock() if p.children != nil { delete(p.children, child) } p.mu.Unlock() } // A canceler is a context type that can be canceled directly. The // implementations are *cancelCtx and *timerCtx. type canceler interface { cancel(removeFromParent bool, err error) Done() <-chan struct{} } // A cancelCtx can be canceled. When canceled, it also cancels any children // that implement canceler. type cancelCtx struct { Context done chan struct{} // closed by the first cancel call. mu sync.Mutex children map[canceler]bool // set to nil by the first cancel call err error // set to non-nil by the first cancel call } func (c *cancelCtx) Done() <-chan struct{} { return c.done } func (c *cancelCtx) Err() error { c.mu.Lock() defer c.mu.Unlock() return c.err } func (c *cancelCtx) String() string { return fmt.Sprintf("%v.WithCancel", c.Context) } // cancel closes c.done, cancels each of c's children, and, if // removeFromParent is true, removes c from its parent's children. func (c *cancelCtx) cancel(removeFromParent bool, err error) { if err == nil { panic("context: internal error: missing cancel error") } c.mu.Lock() if c.err != nil { c.mu.Unlock() return // already canceled } c.err = err close(c.done) for child := range c.children { // NOTE: acquiring the child's lock while holding parent's lock. child.cancel(false, err) } c.children = nil c.mu.Unlock() if removeFromParent { removeChild(c.Context, c) } } // WithDeadline returns a copy of the parent context with the deadline adjusted // to be no later than d. If the parent's deadline is already earlier than d, // WithDeadline(parent, d) is semantically equivalent to parent. The returned // context's Done channel is closed when the deadline expires, when the returned // cancel function is called, or when the parent context's Done channel is // closed, whichever happens first. // // Canceling this context releases resources associated with it, so code should // call cancel as soon as the operations running in this Context complete. func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { // The current deadline is already sooner than the new one. return WithCancel(parent) } c := &timerCtx{ cancelCtx: newCancelCtx(parent), deadline: deadline, } propagateCancel(parent, c) d := deadline.Sub(time.Now()) if d <= 0 { c.cancel(true, DeadlineExceeded) // deadline has already passed return c, func() { c.cancel(true, Canceled) } } c.mu.Lock() defer c.mu.Unlock() if c.err == nil { c.timer = time.AfterFunc(d, func() { c.cancel(true, DeadlineExceeded) }) } return c, func() { c.cancel(true, Canceled) } } // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to // implement Done and Err. It implements cancel by stopping its timer then // delegating to cancelCtx.cancel. type timerCtx struct { *cancelCtx timer *time.Timer // Under cancelCtx.mu. deadline time.Time } func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { return c.deadline, backport/49308/stable29 backport/49308/stable30 backport/49311/stable28 backport/49311/stable29 backport/49311/stable30 backport/49315/stable28 backport/49315/stable29 backport/49315/stable30 backport/49332/stable28 backport/49332/stable29 backport/49332/stable30 backport/49346/stable30 backport/49351/stable29 backport/49351/stable30 backport/49352/stable30 backport/49357/stable30 backport/49361/stable28 backport/49361/stable29 backport/49361/stable30 backport/49372/stable28 backport/49372/stable29 backport/49372/stable30 backport/49373/stable29 backport/49380/stable30 backport/49384/master backport/49398/stable29 backport/49398/stable30 backport/49432/master backport/49432/stable30 backport/49434/stable30 backport/49440/stable29 backport/49440/stable30 backport/49440/stable31 backport/49442/stable28 backport/49442/stable29 backport/49442/stable30 backport/49451/stable29 backport/49451/stable30 backport/49454/stable28 backport/49454/stable29 backport/49454/stable30 backport/49459/stable30 backport/49464/stable28 backport/49464/stable29 backport/49464/stable30 backport/49476/stable28 backport/49476/stable29 backport/49476/stable30 backport/49477/stable30 backport/49489/stable30 backport/49493/stable28 backport/49493/stable29 backport/49494/stable29 backport/49494/stable29-squashed backport/49494/stable30 backport/49503/stable28 backport/49503/stable29 backport/49503/stable30 backport/49528/stable28 backport/49528/stable29 backport/49528/stable30 backport/49551/stable29 backport/49551/stable30 backport/49552/stable28 backport/49552/stable29 backport/49552/stable30 backport/49552/stable31 backport/49557/stable30 backport/49569/stable29 backport/49569/stable30 backport/49581/stable28 backport/49581/stable30 backport/49587/stable30 backport/49588/stable29 backport/49588/stable30 backport/49602/stable28 backport/49602/stable29 backport/49602/stable30 backport/49629/stable29 backport/49631/stable29 backport/49639/stable28 backport/49639/stable29 backport/49639/stable30 backport/49639/stable31 backport/49645/stable31 backport/49677/stable30 backport/49681/stable29 backport/49681/stable30 backport/49685/stable28 backport/49685/stable29 backport/49685/stable30 backport/49693/stable29 backport/49693/stable30 backport/49694/stable30 backport/49695/stable29 backport/49695/stable30 backport/49746/stable30 backport/49747/stable27 backport/49747/stable28 backport/49747/stable29 backport/49747/stable30 backport/49761/stable29 backport/49761/stable30 backport/49799/stable28 backport/49799/stable29 backport/49799/stable30 backport/49801/stable30 backport/49803/stable29 backport/49803/stable30 backport/49815/stable28 backport/49815/stable29 backport/49820/stable30 backport/49822/stable28 backport/49822/stable29 backport/49832/stable30 backport/49839/stable29 backport/49839/stable30 backport/49843/stable29 backport/49843/stable30 backport/49847/stable30 backport/49852/stable30 backport/49880/stable28 backport/49880/stable30 backport/49882/stable28 backport/49882/stable29 backport/49885/stable30 backport/49887/stable29 backport/49887/stable30 backport/49895/stable29 backport/49895/stable30 backport/49898/stable30 backport/49900/stable29 backport/49903/stable29 backport/49903/stable30 backport/49917/stable30 backport/49927/stable28 backport/49962/stable29 backport/49962/stable30 backport/49966/stable29 generated by cgit v1.2.3 (git 2.39.1) at 2025-08-05 03:44:33 +0000