Skip to content

Commit f47004f

Browse files
committed
wip
1 parent 567556d commit f47004f

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/runtime/select.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,43 @@ func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) {
162162
pollorder[j] = uint16(i)
163163
}
164164

165+
// Fast-path: attempt non-blocking operations on all cases; if any
166+
// case succeeds (including if there is a default case), go with it
167+
// and skip locking and all the of the heavy lifting below.
168+
// If none succeed, fallback to the slow-path.
169+
const noDefaultCase = -1
170+
defCase := noDefaultCase
171+
for i := 0; i < ncases; i++ {
172+
n := int(pollorder[i])
173+
cas := scases[n]
174+
switch cas.kind {
175+
case caseRecv:
176+
// TODO: lift/outline the fast path checks from chanrecv
177+
if selected, received := chanrecv(cas.c, cas.elem, false); selected {
178+
return n, received
179+
}
180+
case caseSend:
181+
// TODO: lift/outline the fast path checks from chansend
182+
if chansend(cas.c, cas.elem, false, cas.pc) {
183+
return n, false
184+
}
185+
case caseDefault:
186+
if defCase != -1 {
187+
throw("multiple default cases in select")
188+
}
189+
defCase = n
190+
case caseNil:
191+
// operations on nil channels always block: skip them
192+
default:
193+
throw("unknown select case")
194+
}
195+
}
196+
if defCase != noDefaultCase {
197+
// No non-default case was ready and we have a default case:
198+
// select the default case.
199+
return defCase, false
200+
}
201+
165202
// sort the cases by Hchan address to get the locking order.
166203
// simple heap sort, to guarantee n log n time and constant stack footprint.
167204
for i := 0; i < ncases; i++ {

0 commit comments

Comments
 (0)