| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // +build !go1.7 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package context | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | // An emptyCtx is never canceled, has no values, and has no deadline. It is not | 
					
						
							| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // 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 | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | // *cancelCtx. This function understands how each of the concrete types in this | 
					
						
							| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // 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() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | // A canceler is a context type that can be canceled directly. The | 
					
						
							| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // implementations are *cancelCtx and *timerCtx. | 
					
						
							|  |  |  | type canceler interface { | 
					
						
							|  |  |  | 	cancel(removeFromParent bool, err error) | 
					
						
							|  |  |  | 	Done() <-chan struct{} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | // A cancelCtx can be canceled. When canceled, it also cancels any children | 
					
						
							| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // 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 | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | // 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 | 
					
						
							| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // 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) } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | // 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 | 
					
						
							| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // 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, true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *timerCtx) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *timerCtx) cancel(removeFromParent bool, err error) { | 
					
						
							|  |  |  | 	c.cancelCtx.cancel(false, err) | 
					
						
							|  |  |  | 	if removeFromParent { | 
					
						
							|  |  |  | 		// Remove this timerCtx from its parent cancelCtx's children. | 
					
						
							|  |  |  | 		removeChild(c.cancelCtx.Context, c) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c.mu.Lock() | 
					
						
							|  |  |  | 	if c.timer != nil { | 
					
						
							|  |  |  | 		c.timer.Stop() | 
					
						
							|  |  |  | 		c.timer = nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c.mu.Unlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Canceling this context releases resources associated with it, so code should | 
					
						
							|  |  |  | // call cancel as soon as the operations running in this Context complete: | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // 	func slowOperationWithTimeout(ctx context.Context) (Result, error) { | 
					
						
							|  |  |  | // 		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) | 
					
						
							|  |  |  | // 		defer cancel()  // releases resources if slowOperation completes before timeout elapses | 
					
						
							|  |  |  | // 		return slowOperation(ctx) | 
					
						
							|  |  |  | // 	} | 
					
						
							|  |  |  | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { | 
					
						
							|  |  |  | 	return WithDeadline(parent, time.Now().Add(timeout)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // WithValue returns a copy of parent in which the value associated with key is | 
					
						
							|  |  |  | // val. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Use context Values only for request-scoped data that transits processes and | 
					
						
							|  |  |  | // APIs, not for passing optional parameters to functions. | 
					
						
							|  |  |  | func WithValue(parent Context, key interface{}, val interface{}) Context { | 
					
						
							|  |  |  | 	return &valueCtx{parent, key, val} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | // A valueCtx carries a key-value pair. It implements Value for that key and | 
					
						
							| 
									
										
										
										
											2016-07-14 22:58:17 +02:00
										 |  |  | // delegates all other calls to the embedded Context. | 
					
						
							|  |  |  | type valueCtx struct { | 
					
						
							|  |  |  | 	Context | 
					
						
							|  |  |  | 	key, val interface{} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *valueCtx) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *valueCtx) Value(key interface{}) interface{} { | 
					
						
							|  |  |  | 	if c.key == key { | 
					
						
							|  |  |  | 		return c.val | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return c.Context.Value(key) | 
					
						
							|  |  |  | } |