...
Run Format

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

View as plain text