Skip to content

Commit 7e64bc8

Browse files
cornelkaykevl
authored andcommitted
runtime: add cap and len support for chans
1 parent 1461563 commit 7e64bc8

File tree

4 files changed

+40
-7
lines changed

4 files changed

+40
-7
lines changed

compiler/compiler.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,9 +1201,7 @@ func (b *builder) createBuiltin(args []ssa.Value, callName string, pos token.Pos
12011201
var llvmCap llvm.Value
12021202
switch args[0].Type().(type) {
12031203
case *types.Chan:
1204-
// Channel. Buffered channels haven't been implemented yet so always
1205-
// return 0.
1206-
llvmCap = llvm.ConstInt(b.intType, 0, false)
1204+
llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap")
12071205
case *types.Slice:
12081206
llvmCap = b.CreateExtractValue(value, 2, "cap")
12091207
default:
@@ -1259,9 +1257,7 @@ func (b *builder) createBuiltin(args []ssa.Value, callName string, pos token.Pos
12591257
// string or slice
12601258
llvmLen = b.CreateExtractValue(value, 1, "len")
12611259
case *types.Chan:
1262-
// Channel. Buffered channels haven't been implemented yet so always
1263-
// return 0.
1264-
llvmLen = llvm.ConstInt(b.intType, 0, false)
1260+
llvmLen = b.createRuntimeCall("chanLen", []llvm.Value{value}, "len")
12651261
case *types.Map:
12661262
llvmLen = b.createRuntimeCall("hashmapLen", []llvm.Value{value}, "len")
12671263
default:

src/runtime/chan.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,38 @@ func chanMake(elementSize uintptr, bufSize uintptr) *channel {
136136
}
137137
}
138138

139+
// Return the number of entries in this chan, called from the len builtin.
140+
// A nil chan is defined as having length 0.
141+
//go:inline
142+
func chanLen(c *channel) int {
143+
if c == nil {
144+
return 0
145+
}
146+
return int(c.bufUsed)
147+
}
148+
149+
// wrapper for use in reflect
150+
func chanLenUnsafePointer(p unsafe.Pointer) int {
151+
c := (*channel)(p)
152+
return chanLen(c)
153+
}
154+
155+
// Return the capacity of this chan, called from the cap builtin.
156+
// A nil chan is defined as having capacity 0.
157+
//go:inline
158+
func chanCap(c *channel) int {
159+
if c == nil {
160+
return 0
161+
}
162+
return int(c.bufSize)
163+
}
164+
165+
// wrapper for use in reflect
166+
func chanCapUnsafePointer(p unsafe.Pointer) int {
167+
c := (*channel)(p)
168+
return chanCap(c)
169+
}
170+
139171
// resumeRX resumes the next receiver and returns the destination pointer.
140172
// If the ok value is true, then the caller is expected to store a value into this pointer.
141173
func (ch *channel) resumeRX(ok bool) unsafe.Pointer {

testdata/channel.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import (
99
var wg sync.WaitGroup
1010

1111
func main() {
12-
ch := make(chan int)
12+
ch := make(chan int, 2)
13+
ch <- 1
14+
println("len, cap of channel:", len(ch), cap(ch), ch == nil)
15+
16+
ch = make(chan int)
1317
println("len, cap of channel:", len(ch), cap(ch), ch == nil)
1418

1519
wg.Add(1)

testdata/channel.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
len, cap of channel: 1 2 false
12
len, cap of channel: 0 0 false
23
recv from open channel: 1 true
34
received num: 2

0 commit comments

Comments
 (0)