Source File
chan.go
Belonging Package
runtime
package runtime
import (
)
const (
maxAlign = 8
hchanSize = unsafe.Sizeof(hchan{}) + uintptr(-int(unsafe.Sizeof(hchan{}))&(maxAlign-1))
debugChan = false
)
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
closed uint32
elemtype *_type // element type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
var *hchan
switch {
func ( *hchan, unsafe.Pointer, bool, uintptr) bool {
if == nil {
if ! {
return false
}
gopark(nil, nil, waitReasonChanSendNilChan, traceEvGoStop, 2)
throw("unreachable")
}
if debugChan {
print("chansend: chan=", , "\n")
}
if raceenabled {
racereadpc(.raceaddr(), , funcPC())
}
:= getg()
:= acquireSudog()
.releasetime = 0
if != 0 {
.releasetime = -1
atomic.Store8(&.parkingOnChan, 1)
if != .waiting {
throw("G waiting list is corrupted")
}
.waiting = nil
.activeStackChans = false
:= !.success
.param = nil
if .releasetime > 0 {
blockevent(.releasetime-, 2)
}
.c = nil
releaseSudog()
if {
if .closed == 0 {
throw("chansend: spurious wakeup")
}
panic(plainError("send on closed channel"))
}
return true
}
racenotify(, .recvx, nil)
racenotify(, .recvx, )
.recvx++
if .recvx == .dataqsiz {
.recvx = 0
}
.sendx = .recvx // c.sendx = (c.sendx+1) % c.dataqsiz
}
}
if .elem != nil {
sendDirect(.elemtype, , )
.elem = nil
}
:= .g
()
.param = unsafe.Pointer()
.success = true
if .releasetime != 0 {
.releasetime = cputicks()
}
goready(, +1)
}
:= .elem
:= .elem
typeBitsBulkBarrier(, uintptr(), uintptr(), .size)
memmove(, , .size)
}
func ( *hchan) {
if == nil {
panic(plainError("close of nil channel"))
}
lock(&.lock)
if .closed != 0 {
unlock(&.lock)
panic(plainError("close of closed channel"))
}
if raceenabled {
:= getcallerpc()
racewritepc(.raceaddr(), , funcPC())
racerelease(.raceaddr())
}
.closed = 1
var gList
for {
:= .recvq.dequeue()
if == nil {
break
}
if .elem != nil {
typedmemclr(.elemtype, .elem)
.elem = nil
}
if .releasetime != 0 {
.releasetime = cputicks()
}
:= .g
.param = unsafe.Pointer()
.success = false
if raceenabled {
raceacquireg(, .raceaddr())
}
.push()
}
for {
:= .sendq.dequeue()
if == nil {
break
}
.elem = nil
if .releasetime != 0 {
.releasetime = cputicks()
}
:= .g
.param = unsafe.Pointer()
.success = false
if raceenabled {
raceacquireg(, .raceaddr())
}
.push()
}
unlock(&.lock)
if debugChan {
print("chanrecv: chan=", , "\n")
}
if == nil {
if ! {
return
}
gopark(nil, nil, waitReasonChanReceiveNilChan, traceEvGoStop, 2)
throw("unreachable")
}
return
if raceenabled {
raceacquire(.raceaddr())
}
if != nil {
typedmemclr(.elemtype, )
}
return true, false
}
}
var int64
if blockprofilerate > 0 {
= cputicks()
}
lock(&.lock)
if .closed != 0 && .qcount == 0 {
if raceenabled {
raceacquire(.raceaddr())
}
unlock(&.lock)
if != nil {
typedmemclr(.elemtype, )
}
return true, false
}
:= getg()
:= acquireSudog()
.releasetime = 0
if != 0 {
.releasetime = -1
if != .waiting {
throw("G waiting list is corrupted")
}
.waiting = nil
.activeStackChans = false
if .releasetime > 0 {
blockevent(.releasetime-, 2)
}
:= .success
.param = nil
.c = nil
releaseSudog()
return true,
}
recvDirect(.elemtype, , )
}
:= chanbuf(, .recvx)
if raceenabled {
racenotify(, .recvx, nil)
racenotify(, .recvx, )
if != nil {
typedmemmove(.elemtype, , )
func ( *hchan) {
closechan()
}
func ( *waitq) ( *sudog) {
.next = nil
:= .last
if == nil {
.prev = nil
.first =
.last =
return
}
.prev =
.next =
.last =
}
func ( *waitq) () *sudog {
for {
:= .first
if == nil {
return nil
}
:= .next
if == nil {
.first = nil
.last = nil
} else {
.prev = nil
.first =
.next = nil // mark as removed (see dequeueSudog)
}
if .isSelect && !atomic.Cas(&.g.selectDone, 0, 1) {
continue
}
return
}
}
return unsafe.Pointer(&.buf)
}
func ( *hchan, *sudog) {
racerelease(chanbuf(, 0))
raceacquireg(.g, chanbuf(, 0))
racereleaseg(.g, chanbuf(, 0))
raceacquire(chanbuf(, 0))
}
if .elemsize == 0 {
if == nil {
raceacquire()
racerelease()
} else {
raceacquireg(.g, )
racereleaseg(.g, )
}
} else {
if == nil {
racereleaseacquire()
} else {
racereleaseacquireg(.g, )
}
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |