func propagateCancel(parent Context, child canceler) {
	if parent.Done() == nil {
		return  
	}
	if p, ok := parentCancelCtx(parent); ok {
		p.cancelLock.Lock()
		if p.err != nil {
			p.cancelLock.Unlock()
			child.cancel(false, p.err)
		} else {
			p.childrenLock.Lock()
			if p.children == nil {
				p.children = make(map[canceler]bool)
			}
			p.children[child] = true
			p.childrenLock.Unlock()
			p.cancelLock.Unlock()
		}
	} else {
		go func() {
			s := NewSelector(parent)
			s.AddReceive(parent.Done(), func(c Channel, more bool) {
				child.cancel(false, parent.Err())
			})
			s.AddReceive(child.Done(), func(c Channel, more bool) {})
			s.Select(parent)
		}()
	}
}
propagateCancel arranges for child to be canceled when parent is.
package internal
import (
	"fmt"
	"sync"
	"time"
	"github.com/opentracing/opentracing-go"
	"go.uber.org/cadence/.gen/go/shared"
)
const activeSpanContextKey contextKey = "activeSpanContextKey"
type Context interface {
	Deadline() (deadline time.Time, ok bool)
	Done() Channel
	Err() error
	Value(key interface{}) interface{}
}
type emptyCtx int
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
	return
}
func (*emptyCtx) Done() Channel {
	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)
)
func Background() Context {
	return background
}
var ErrCanceled = NewCanceledError()
var ErrDeadlineExceeded = NewTimeoutError(shared.TimeoutTypeScheduleToClose)
type CancelFunc func()
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
	c := newCancelCtx(parent)
	propagateCancel(parent, c)
	return c, func() { c.cancel(true, ErrCanceled) }
}
func NewDisconnectedContext(parent Context) (ctx Context, cancel CancelFunc) {
	c := newCancelCtx(parent)
	return c, func() { c.cancel(true, ErrCanceled) }
}
func newCancelCtx(parent Context) *cancelCtx {
	return &cancelCtx{
		Context: parent,
		done:    NewNamedChannel(parent, "cancelCtx-done-channel"),
	}
}