返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

5.1 创建

发布于 2024-10-12 19:16:07 字数 1494 浏览 0 评论 0 收藏 0

同步和异步通道的区别在于是否创建缓冲区。

// chan.go

type hchan struct {
    qcount   uint             // 数据项数量。
    dataqsiz uint             // 缓冲区容量。
    buf      unsafe.Pointer   // 缓冲区指针。
    
    elemsize uint16           // 元素长度。
    elemtype *_type           // 元素类型。
    
    closed   uint32
    
    sendx    uint             // 缓冲区发送索引。
    recvx    uint             // 缓冲区接收索引。
    recvq    waitq            // 接收等待列表。
    sendq    waitq            // 发送等待列表。
    
    lock mutex
}

根据是否包含指针,来选择内存分配模式。

func makechan(t *chantype, size int) *hchan {

    elem := t.elem
    
    // 元素长度不能超过 64KB。
    if elem.size >= 1<<16 {
        throw("makechan: invalid channel element type")
    }
    
    // 缓冲区内存限制。
    mem, overflow := math.MulUintptr(elem.size, uintptr(size))  // 元素大小 * 数量
    if overflow || mem > maxAlloc-hchanSize || size < 0 {
        panic(plainError("makechan: size out of range"))
    }
    
    var c *hchan
    switch {
    case mem == 0:
        // 队列或元素长度为零,不分配缓冲区。
        c = (*hchan)(mallocgc(hchanSize, nil, true))
        c.buf = unsafe.Pointer(c)
    case elem.ptrdata == 0:
        // 非指针类型,连同缓冲区一同分配。
        c = (*hchan)(mallocgc(hchanSize+mem, nil, true))
        c.buf = add(unsafe.Pointer(c), hchanSize)
    default:
        // 单独分配内存。
        c = new(hchan)
        c.buf = mallocgc(mem, elem, true)
    }
    
    c.elemsize = uint16(elem.size)
    c.elemtype = elem
    c.dataqsiz = uint(size)
    
    return c
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文