...

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		"time"
    55	)
    56	
    57	// A Context carries a deadline, a cancellation signal, and other values across
    58	// API boundaries.
    59	//
    60	// Context's methods may be called by multiple goroutines simultaneously.
    61	type Context interface {
    62		// Deadline returns the time when work done on behalf of this context
    63		// should be canceled. Deadline returns ok==false when no deadline is
    64		// set. Successive calls to Deadline return the same results.
    65		Deadline() (deadline time.Time, ok bool)
    66	
    67		// Done returns a channel that's closed when work done on behalf of this
    68		// context should be canceled. Done may return nil if this context can
    69		// never be canceled. Successive calls to Done return the same value.
    70		//
    71		// WithCancel arranges for Done to be closed when cancel is called;
    72		// WithDeadline arranges for Done to be closed when the deadline
    73		// expires; WithTimeout arranges for Done to be closed when the timeout
    74		// elapses.
    75		//
    76		// Done is provided for use in select statements:
    77		//
    78		//  // Stream generates values with DoSomething and sends them to out
    79		//  // until DoSomething returns an error or ctx.Done is closed.
    80		//  func Stream(ctx context.Context, out chan<- Value) error {
    81		//  	for {
    82		//  		v, err := DoSomething(ctx)
    83		//  		if err != nil {
    84		//  			return err
    85		//  		}
    86		//  		select {
    87		//  		case <-ctx.Done():
    88		//  			return ctx.Err()
    89		//  		case out <- v:
    90		//  		}
    91		//  	}
    92		//  }
    93		//
    94		// See https://blog.golang.org/pipelines for more examples of how to use
    95		// a Done channel for cancellation.
    96		Done() <-chan struct{}
    97	
    98		// If Done is not yet closed, Err returns nil.
    99		// If Done is closed, Err returns a non-nil error explaining why:
   100		// Canceled if the context was canceled
   101		// or DeadlineExceeded if the context's deadline passed.
   102		// After Err returns a non-nil error, successive calls to Err return the same error.
   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
   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).
   213	func TODO() Context {
   214		return todo
   215	}
   216	
   217	// A CancelFunc tells an operation to abandon its work.
   218	// A CancelFunc does not wait for the work to stop.
   219	// A CancelFunc may be called by multiple goroutines simultaneously.
   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{Context: parent}
   238	}
   239	
   240	// propagateCancel arranges for child to be canceled when parent is.
   241	func propagateCancel(parent Context, child canceler) {
   242		if parent.Done() == nil {
   243			return // parent is never canceled
   244		}
   245		if p, ok := parentCancelCtx(parent); ok {
   246			p.mu.Lock()
   247			if p.err != nil {
   248				// parent has already been canceled
   249				child.cancel(false, p.err)
   250			} else {
   251				if p.children == nil {
   252					p.children = make(map[canceler]struct{})
   253				}
   254				p.children[child] = struct{}{}
   255			}
   256			p.mu.Unlock()
   257		} else {
   258			go func() {
   259				select {
   260				case <-parent.Done():
   261					child.cancel(false, parent.Err())
   262				case <-child.Done():
   263				}
   264			}()
   265		}
   266	}
   267	
   268	// parentCancelCtx follows a chain of parent references until it finds a
   269	// *cancelCtx. This function understands how each of the concrete types in this
   270	// package represents its parent.
   271	func parentCancelCtx(parent Context) (*cancelCtx, bool) {
   272		for {
   273			switch c := parent.(type) {
   274			case *cancelCtx:
   275				return c, true
   276			case *timerCtx:
   277				return &c.cancelCtx, true
   278			case *valueCtx:
   279				parent = c.Context
   280			default:
   281				return nil, false
   282			}
   283		}
   284	}
   285	
   286	// removeChild removes a context from its parent.
   287	func removeChild(parent Context, child canceler) {
   288		p, ok := parentCancelCtx(parent)
   289		if !ok {
   290			return
   291		}
   292		p.mu.Lock()
   293		if p.children != nil {
   294			delete(p.children, child)
   295		}
   296		p.mu.Unlock()
   297	}
   298	
   299	// A canceler is a context type that can be canceled directly. The
   300	// implementations are *cancelCtx and *timerCtx.
   301	type canceler interface {
   302		cancel(removeFromParent bool, err error)
   303		Done() <-chan struct{}
   304	}
   305	
   306	// closedchan is a reusable closed channel.
   307	var closedchan = make(chan struct{})
   308	
   309	func init() {
   310		close(closedchan)
   311	}
   312	
   313	// A cancelCtx can be canceled. When canceled, it also cancels any children
   314	// that implement canceler.
   315	type cancelCtx struct {
   316		Context
   317	
   318		mu       sync.Mutex            // protects following fields
   319		done     chan struct{}         // created lazily, closed by first cancel call
   320		children map[canceler]struct{} // set to nil by the first cancel call
   321		err      error                 // set to non-nil by the first cancel call
   322	}
   323	
   324	func (c *cancelCtx) Done() <-chan struct{} {
   325		c.mu.Lock()
   326		if c.done == nil {
   327			c.done = make(chan struct{})
   328		}
   329		d := c.done
   330		c.mu.Unlock()
   331		return d
   332	}
   333	
   334	func (c *cancelCtx) Err() error {
   335		c.mu.Lock()
   336		err := c.err
   337		c.mu.Unlock()
   338		return err
   339	}
   340	
   341	type stringer interface {
   342		String() string
   343	}
   344	
   345	func contextName(c Context) string {
   346		if s, ok := c.(stringer); ok {
   347			return s.String()
   348		}
   349		return reflectlite.TypeOf(c).String()
   350	}
   351	
   352	func (c *cancelCtx) String() string {
   353		return contextName(c.Context) + ".WithCancel"
   354	}
   355	
   356	// cancel closes c.done, cancels each of c's children, and, if
   357	// removeFromParent is true, removes c from its parent's children.
   358	func (c *cancelCtx) cancel(removeFromParent bool, err error) {
   359		if err == nil {
   360			panic("context: internal error: missing cancel error")
   361		}
   362		c.mu.Lock()
   363		if c.err != nil {
   364			c.mu.Unlock()
   365			return // already canceled
   366		}
   367		c.err = err
   368		if c.done == nil {
   369			c.done = closedchan
   370		} else {
   371			close(c.done)
   372		}
   373		for child := range c.children {
   374			// NOTE: acquiring the child's lock while holding parent's lock.
   375			child.cancel(false, err)
   376		}
   377		c.children = nil
   378		c.mu.Unlock()
   379	
   380		if removeFromParent {
   381			removeChild(c.Context, c)
   382		}
   383	}
   384	
   385	// WithDeadline returns a copy of the parent context with the deadline adjusted
   386	// to be no later than d. If the parent's deadline is already earlier than d,
   387	// WithDeadline(parent, d) is semantically equivalent to parent. The returned
   388	// context's Done channel is closed when the deadline expires, when the returned
   389	// cancel function is called, or when the parent context's Done channel is
   390	// closed, whichever happens first.
   391	//
   392	// Canceling this context releases resources associated with it, so code should
   393	// call cancel as soon as the operations running in this Context complete.
   394	func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
   395		if cur, ok := parent.Deadline(); ok && cur.Before(d) {
   396			// The current deadline is already sooner than the new one.
   397			return WithCancel(parent)
   398		}
   399		c := &timerCtx{
   400			cancelCtx: newCancelCtx(parent),
   401			deadline:  d,
   402		}
   403		propagateCancel(parent, c)
   404		dur := time.Until(d)
   405		if dur <= 0 {
   406			c.cancel(true, DeadlineExceeded) // deadline has already passed
   407			return c, func() { c.cancel(false, Canceled) }
   408		}
   409		c.mu.Lock()
   410		defer c.mu.Unlock()
   411		if c.err == nil {
   412			c.timer = time.AfterFunc(dur, func() {
   413				c.cancel(true, DeadlineExceeded)
   414			})
   415		}
   416		return c, func() { c.cancel(true, Canceled) }
   417	}
   418	
   419	// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
   420	// implement Done and Err. It implements cancel by stopping its timer then
   421	// delegating to cancelCtx.cancel.
   422	type timerCtx struct {
   423		cancelCtx
   424		timer *time.Timer // Under cancelCtx.mu.
   425	
   426		deadline time.Time
   427	}
   428	
   429	func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
   430		return c.deadline, true
   431	}
   432	
   433	func (c *timerCtx) String() string {
   434		return contextName(c.cancelCtx.Context) + ".WithDeadline(" +
   435			c.deadline.String() + " [" +
   436			time.Until(c.deadline).String() + "])"
   437	}
   438	
   439	func (c *timerCtx) cancel(removeFromParent bool, err error) {
   440		c.cancelCtx.cancel(false, err)
   441		if removeFromParent {
   442			// Remove this timerCtx from its parent cancelCtx's children.
   443			removeChild(c.cancelCtx.Context, c)
   444		}
   445		c.mu.Lock()
   446		if c.timer != nil {
   447			c.timer.Stop()
   448			c.timer = nil
   449		}
   450		c.mu.Unlock()
   451	}
   452	
   453	// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
   454	//
   455	// Canceling this context releases resources associated with it, so code should
   456	// call cancel as soon as the operations running in this Context complete:
   457	//
   458	// 	func slowOperationWithTimeout(ctx context.Context) (Result, error) {
   459	// 		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
   460	// 		defer cancel()  // releases resources if slowOperation completes before timeout elapses
   461	// 		return slowOperation(ctx)
   462	// 	}
   463	func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
   464		return WithDeadline(parent, time.Now().Add(timeout))
   465	}
   466	
   467	// WithValue returns a copy of parent in which the value associated with key is
   468	// val.
   469	//
   470	// Use context Values only for request-scoped data that transits processes and
   471	// APIs, not for passing optional parameters to functions.
   472	//
   473	// The provided key must be comparable and should not be of type
   474	// string or any other built-in type to avoid collisions between
   475	// packages using context. Users of WithValue should define their own
   476	// types for keys. To avoid allocating when assigning to an
   477	// interface{}, context keys often have concrete type
   478	// struct{}. Alternatively, exported context key variables' static
   479	// type should be a pointer or interface.
   480	func WithValue(parent Context, key, val interface{}) Context {
   481		if key == nil {
   482			panic("nil key")
   483		}
   484		if !reflectlite.TypeOf(key).Comparable() {
   485			panic("key is not comparable")
   486		}
   487		return &valueCtx{parent, key, val}
   488	}
   489	
   490	// A valueCtx carries a key-value pair. It implements Value for that key and
   491	// delegates all other calls to the embedded Context.
   492	type valueCtx struct {
   493		Context
   494		key, val interface{}
   495	}
   496	
   497	// stringify tries a bit to stringify v, without using fmt, since we don't
   498	// want context depending on the unicode tables. This is only used by
   499	// *valueCtx.String().
   500	func stringify(v interface{}) string {
   501		switch s := v.(type) {
   502		case stringer:
   503			return s.String()
   504		case string:
   505			return s
   506		}
   507		return "<not Stringer>"
   508	}
   509	
   510	func (c *valueCtx) String() string {
   511		return contextName(c.Context) + ".WithValue(type " +
   512			reflectlite.TypeOf(c.key).String() +
   513			", val " + stringify(c.val) + ")"
   514	}
   515	
   516	func (c *valueCtx) Value(key interface{}) interface{} {
   517		if c.key == key {
   518			return c.val
   519		}
   520		return c.Context.Value(key)
   521	}
   522	

View as plain text