runtime: close(chan)
This commit is contained in:
@@ -24,4 +24,26 @@ func doChan(cap int) {
|
||||
func main() {
|
||||
doChan(10)
|
||||
doChan(0)
|
||||
|
||||
c := runtime.NewChan(eltSize, 3)
|
||||
|
||||
v := 1
|
||||
runtime.ChanSend(c, unsafe.Pointer(&v), eltSize)
|
||||
v = 2
|
||||
runtime.ChanSend(c, unsafe.Pointer(&v), eltSize)
|
||||
v = 3
|
||||
runtime.ChanSend(c, unsafe.Pointer(&v), eltSize)
|
||||
runtime.ChanClose(c)
|
||||
|
||||
v = 10
|
||||
if runtime.ChanTrySend(c, unsafe.Pointer(&v), eltSize) {
|
||||
println("error: chan send to closed chan")
|
||||
}
|
||||
|
||||
for {
|
||||
if ok := runtime.ChanRecv(c, unsafe.Pointer(&v), eltSize); !ok {
|
||||
break
|
||||
}
|
||||
println(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ import (
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const chanFull = 1
|
||||
const (
|
||||
chanFull = 1
|
||||
)
|
||||
|
||||
type Chan struct {
|
||||
mutex sync.Mutex
|
||||
@@ -34,6 +36,7 @@ type Chan struct {
|
||||
getp int
|
||||
len int
|
||||
cap int
|
||||
close bool
|
||||
}
|
||||
|
||||
func NewChan(eltSize, cap int) *Chan {
|
||||
@@ -57,18 +60,25 @@ func ChanCap(p *Chan) int {
|
||||
return p.cap
|
||||
}
|
||||
|
||||
func ChanClose(p *Chan) {
|
||||
p.mutex.Lock()
|
||||
p.close = true
|
||||
p.mutex.Unlock()
|
||||
p.cond.Broadcast()
|
||||
}
|
||||
|
||||
func ChanTrySend(p *Chan, v unsafe.Pointer, eltSize int) bool {
|
||||
n := p.cap
|
||||
p.mutex.Lock()
|
||||
if n == 0 {
|
||||
if p.getp == chanFull {
|
||||
if p.getp == chanFull || p.close {
|
||||
p.mutex.Unlock()
|
||||
return false
|
||||
}
|
||||
p.data = v
|
||||
p.getp = chanFull
|
||||
} else {
|
||||
if p.len == n {
|
||||
if p.len == n || p.close {
|
||||
p.mutex.Unlock()
|
||||
return false
|
||||
}
|
||||
@@ -81,25 +91,34 @@ func ChanTrySend(p *Chan, v unsafe.Pointer, eltSize int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func ChanSend(p *Chan, v unsafe.Pointer, eltSize int) {
|
||||
func ChanSend(p *Chan, v unsafe.Pointer, eltSize int) bool {
|
||||
n := p.cap
|
||||
p.mutex.Lock()
|
||||
if n == 0 {
|
||||
for p.getp == chanFull {
|
||||
p.cond.Wait(&p.mutex)
|
||||
}
|
||||
if p.close {
|
||||
p.mutex.Unlock()
|
||||
return false
|
||||
}
|
||||
p.data = v
|
||||
p.getp = chanFull
|
||||
} else {
|
||||
for p.len == n {
|
||||
p.cond.Wait(&p.mutex)
|
||||
}
|
||||
if p.close {
|
||||
p.mutex.Unlock()
|
||||
return false
|
||||
}
|
||||
off := (p.getp + p.len) % n
|
||||
c.Memcpy(c.Advance(p.data, off*eltSize), v, uintptr(eltSize))
|
||||
p.len++
|
||||
}
|
||||
p.mutex.Unlock()
|
||||
p.cond.Broadcast()
|
||||
return true
|
||||
}
|
||||
|
||||
func ChanTryRecv(p *Chan, v unsafe.Pointer, eltSize int) bool {
|
||||
@@ -126,17 +145,25 @@ func ChanTryRecv(p *Chan, v unsafe.Pointer, eltSize int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func ChanRecv(p *Chan, v unsafe.Pointer, eltSize int) {
|
||||
func ChanRecv(p *Chan, v unsafe.Pointer, eltSize int) bool {
|
||||
n := p.cap
|
||||
p.mutex.Lock()
|
||||
if n == 0 {
|
||||
for p.getp == 0 {
|
||||
if p.close {
|
||||
p.mutex.Unlock()
|
||||
return false
|
||||
}
|
||||
p.cond.Wait(&p.mutex)
|
||||
}
|
||||
c.Memcpy(v, p.data, uintptr(eltSize))
|
||||
p.getp = 0
|
||||
} else {
|
||||
for p.len == 0 {
|
||||
if p.close {
|
||||
p.mutex.Unlock()
|
||||
return false
|
||||
}
|
||||
p.cond.Wait(&p.mutex)
|
||||
}
|
||||
c.Memcpy(v, c.Advance(p.data, p.getp*eltSize), uintptr(eltSize))
|
||||
@@ -145,6 +172,7 @@ func ChanRecv(p *Chan, v unsafe.Pointer, eltSize int) {
|
||||
}
|
||||
p.mutex.Unlock()
|
||||
p.cond.Broadcast()
|
||||
return true
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user