@@ -162,6 +162,43 @@ func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) {
162
162
pollorder [j ] = uint16 (i )
163
163
}
164
164
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
+
165
202
// sort the cases by Hchan address to get the locking order.
166
203
// simple heap sort, to guarantee n log n time and constant stack footprint.
167
204
for i := 0 ; i < ncases ; i ++ {
0 commit comments