package context
import (
"time"
)
// timerCtx 带计时器和截止日期的 cancelCtx
type timerCtx struct {
cancelCtx
timer *time.Timer // 依赖 cancelCtx.mu
deadline time.Time // context 截止时间
}
func (c *timerCtx) Deadline() (time.Time, bool) {
return c.deadline, true
}
func (c *timerCtx) String() string {
return contextName(c.cancelCtx.Context) + ".WithDeadline(" + c.deadline.String() + " [" + time.Until(c.deadline).String() + "])"
}
package context
import "reflect"
// valueCtx 储存键值对 context
type valueCtx struct {
Context
key, val interface{}
}
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key {
return c.val
}
return c.Context.Value(key)
}
// stringify tries a bit to stringify v, without using fmt, since we don't
// want context depending on the unicode tables. This is only used by *valueCtx.String()
func stringify(v interface{}) string {
switch s := v.(type) {
case stringer:
return s.String()
case string:
return s
}
return "<not Stringer>"
}
func (c *valueCtx) String() string {
return contextName(c.Context) + ".WithValue(type " + reflect.TypeOf(c.key).String() + ", val " + stringify(c.val) + ")"
}
package context
import (
"reflect"
"time"
)
// WithValue returns a copy of parent in which the value associated with key is val
func WithValue(parent Context, key, val interface{}) Context {
if key == nil {
panic("nil key")
}
// key 不具备可比性时候, 会引发运行时恐慌 panic
if !reflect.TypeOf(key).Comparable() {
panic("key is not comparable")
}
return &valueCtx{parent, key, val}
}
// parentCancelCtx 获取 parent CancelCtx
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()
}
// closedchan 可重复使用且已经关闭通道
var closedchan = make