github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/context/context.go (about)

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