设为首页 加入收藏

TOP

带小伙伴手写 golang context(八)
2019-05-23 14:33:29 】 浏览:364
Tags:小伙伴 手写 golang context
(chan struct{}) func init() { close(closedchan) } // cancel cancelCtx 取消操作, 关闭 c.done, 取消每个 child context, removeFromParent is true 从 parent 删除 child func (c *cancelCtx) cancel(removeFromParent bool, err error) { c.mu.Lock() if c.err != nil { c.mu.Unlock() return // already canceled } c.err = err if c.done == nil { c.done = closedchan } else { close(c.done) } for child := range c.children { // NOTE: 保留 parent 锁, 继续获取 child 锁 child.cancel(false, err) } c.children = nil c.mu.Unlock() if removeFromParent { removeChild(c.Context, c) } } // cancel timerCtx 取消操作 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() } // propagateCancel parent 取消 map 中添加 child 子项 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]struct{}) } p.children[child] = struct{}{} } p.mu.Unlock() } else { go func() { select { case <-parent.Done(): child.cancel(false, parent.Err()) case <-child.Done(): } }() } } // CancelFunc cancel func 行为 type CancelFunc func() // WithCancel 基于 parent context 构造可取消的 child context func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := newCancelCtx(parent) propagateCancel(parent, &c) return &c, func() { c.cancel(true, Canceled) } } // WithDeadline 返回 child context 并调整 parent deadline func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) { if cur, ok := parent.Deadline(); ok && cur.Before(d) { // 当前截止日期早于新设置的截止日期, 直接使用当前截止日期 return WithCancel(parent) } c := &timerCtx{ cancelCtx: newCancelCtx(parent), deadline: d, } propagateCancel(parent, c) dur := time.Until(d) if dur <= 0 { c.cancel(true, DeadlineExceeded) // deadline has already passed return c, func() { c.cancel(false, Canceled) } } c.mu.Lock() defer c.mu.Unlock() if c.err == nil { c.timer = time.AfterFunc(dur, func() { c.cancel(true, DeadlineExceeded) }) } return c, func() { c.cancel(true, Canceled) } } // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)) func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { return WithDeadline(parent, time.Now().Add(timeout)) } 

看到 with.go 是不是有种 mmp 感觉, 第一问还好, 第二问也爽爽, 这第三问怎么就有了压轴最后一问思索感 ~ 

其实还好, 多关怀下 propagateCancel 和 cancelCtx.cancel 操作怎么打配合.  其实上面源码中最难写的是

reflect 和 time (errors 和 sync 接触多好理解) 有兴趣的同行可以深入研究 . 水文该说再见了, 希望大家有

所得 ~ 

后记 - 代码和注释并存

  错误是难免的, 欢迎勘误 ~ 共同成长提高 ?

 <窗外雨>https://music.163.com/#/song?id=514543382

 

 

首页 上一页 5 6 7 8 下一页 尾页 8/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇golang 变量定义 下一篇simple go web application & 二..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目