返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

5.1 创建

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

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

// chan.go

type hchan struct {
	qcount   uint           // total data in the queue
	dataqsiz uint           // size of the circular queue
	buf      unsafe.Pointer // points to an array of dataqsiz elements
    
	elemsize uint16
	elemtype *_type // element type
    
	closed   uint32
    
	sendx    uint   // send index
	recvx    uint   // receive index
	recvq    waitq  // list of recv waiters
	sendq    waitq  // list of send waiters

	// lock protects all fields in hchan, as well as several
	// fields in sudogs blocked on this channel.
	//
	// Do not change another G's status while holding this lock
	// (in particular, do not ready a G), as this can deadlock
	// with stack shrinking.
	lock mutex
}

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

func makechan(t *chantype, size int) *hchan {
	elem := t.elem

    // 元素长度不能超过 64 KB。
	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:
        // 队列或元素长度为零,不分配缓冲区。(hchanSize = sizeof hchan)
		c = (*hchan)(mallocgc(hchanSize, nil, true))
		c.buf = c.raceaddr()
	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)
    
	lockInit(&c.lock, lockRankHchan)
	return c
}

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

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

发布评论

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