runtime: add cap and len support for chans
Этот коммит содержится в:
родитель
1461563e3f
коммит
7e64bc8f77
4 изменённых файлов: 40 добавлений и 7 удалений
|
@ -1201,9 +1201,7 @@ func (b *builder) createBuiltin(args []ssa.Value, callName string, pos token.Pos
|
|||
var llvmCap llvm.Value
|
||||
switch args[0].Type().(type) {
|
||||
case *types.Chan:
|
||||
// Channel. Buffered channels haven't been implemented yet so always
|
||||
// return 0.
|
||||
llvmCap = llvm.ConstInt(b.intType, 0, false)
|
||||
llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap")
|
||||
case *types.Slice:
|
||||
llvmCap = b.CreateExtractValue(value, 2, "cap")
|
||||
default:
|
||||
|
@ -1259,9 +1257,7 @@ func (b *builder) createBuiltin(args []ssa.Value, callName string, pos token.Pos
|
|||
// string or slice
|
||||
llvmLen = b.CreateExtractValue(value, 1, "len")
|
||||
case *types.Chan:
|
||||
// Channel. Buffered channels haven't been implemented yet so always
|
||||
// return 0.
|
||||
llvmLen = llvm.ConstInt(b.intType, 0, false)
|
||||
llvmLen = b.createRuntimeCall("chanLen", []llvm.Value{value}, "len")
|
||||
case *types.Map:
|
||||
llvmLen = b.createRuntimeCall("hashmapLen", []llvm.Value{value}, "len")
|
||||
default:
|
||||
|
|
|
@ -136,6 +136,38 @@ func chanMake(elementSize uintptr, bufSize uintptr) *channel {
|
|||
}
|
||||
}
|
||||
|
||||
// Return the number of entries in this chan, called from the len builtin.
|
||||
// A nil chan is defined as having length 0.
|
||||
//go:inline
|
||||
func chanLen(c *channel) int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return int(c.bufUsed)
|
||||
}
|
||||
|
||||
// wrapper for use in reflect
|
||||
func chanLenUnsafePointer(p unsafe.Pointer) int {
|
||||
c := (*channel)(p)
|
||||
return chanLen(c)
|
||||
}
|
||||
|
||||
// Return the capacity of this chan, called from the cap builtin.
|
||||
// A nil chan is defined as having capacity 0.
|
||||
//go:inline
|
||||
func chanCap(c *channel) int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return int(c.bufSize)
|
||||
}
|
||||
|
||||
// wrapper for use in reflect
|
||||
func chanCapUnsafePointer(p unsafe.Pointer) int {
|
||||
c := (*channel)(p)
|
||||
return chanCap(c)
|
||||
}
|
||||
|
||||
// resumeRX resumes the next receiver and returns the destination pointer.
|
||||
// If the ok value is true, then the caller is expected to store a value into this pointer.
|
||||
func (ch *channel) resumeRX(ok bool) unsafe.Pointer {
|
||||
|
|
6
testdata/channel.go
предоставленный
6
testdata/channel.go
предоставленный
|
@ -9,7 +9,11 @@ import (
|
|||
var wg sync.WaitGroup
|
||||
|
||||
func main() {
|
||||
ch := make(chan int)
|
||||
ch := make(chan int, 2)
|
||||
ch <- 1
|
||||
println("len, cap of channel:", len(ch), cap(ch), ch == nil)
|
||||
|
||||
ch = make(chan int)
|
||||
println("len, cap of channel:", len(ch), cap(ch), ch == nil)
|
||||
|
||||
wg.Add(1)
|
||||
|
|
1
testdata/channel.txt
предоставленный
1
testdata/channel.txt
предоставленный
|
@ -1,3 +1,4 @@
|
|||
len, cap of channel: 1 2 false
|
||||
len, cap of channel: 0 0 false
|
||||
recv from open channel: 1 true
|
||||
received num: 2
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче