nbsp; // 从发送等待队列中取出 sudog
sg = c.sendq.dequeue()
if sg == nil {
throw("chan send inconsistency")
}
// 将数据复制到队列中
qput(c, i, ep)
}
// 更新发送位置
c.sendx++
// 释放锁
unlock(&c.lock)
return true
}
func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {
// 获取 chan 的锁
lock(&c.lock)
// 检查 chan 是否已经关闭
if c.closed != 0 && c.qcount == 0 {
unlock(&c.lock)
return false, false
}
// 计算接收位置
i := c.recvx
// 如果队列中没有数据,需要将当前 goroutine 加入到接收等待队列中
if c.qcount <= 0 {
g := getg()
gp := g.m.curg
if !block {
unlock(&c.lock)
return false, false
}
// 创建一个 sudog,表示当前 goroutine 等待接收
sg := acquireSudog()
sg.releasetime = 0
sg.acquiretime = 0
sg.g = gp
sg.elem = ep
sg.c = c
// 将 sudog 加入到接收等待队列中
c.recvq.enqueue(sg)
// 释放锁,并将当前 goroutine 阻塞
unlock(&c.lock)
park_m(gp, waitReasonChanReceive, traceEvGoBlockRecv, 1)