}
}
+func TestSelectMaxCases(t *testing.T) {
+ var sCases []SelectCase
+ channel := make(chan int)
+ close(channel)
+ for i := 0; i < 65536; i++ {
+ sCases = append(sCases, SelectCase{
+ Dir: SelectRecv,
+ Chan: ValueOf(channel),
+ })
+ }
+ // Should not panic
+ _, _, _ = Select(sCases)
+ sCases = append(sCases, SelectCase{
+ Dir: SelectRecv,
+ Chan: ValueOf(channel),
+ })
+ defer func() {
+ if err := recover(); err != nil {
+ if err.(string) != "reflect.Select: too many cases (max 65536)" {
+ t.Fatalf("unexpected error from select call with greater than max supported cases")
+ }
+ } else {
+ t.Fatalf("expected select call to panic with greater than max supported cases")
+ }
+ }()
+ // Should panic
+ _, _, _ = Select(sCases)
+}
+
// selectWatch and the selectWatcher are a watchdog mechanism for running Select.
// If the selectWatcher notices that the select has been blocked for >1 second, it prints
// an error describing the select and panics the entire test binary.
// and, if that case was a receive operation, the value received and a
// boolean indicating whether the value corresponds to a send on the channel
// (as opposed to a zero value received because the channel is closed).
+// Select supports a maximum of 65536 cases.
func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
+ if len(cases) > 65536 {
+ panic("reflect.Select: too many cases (max 65536)")
+ }
// NOTE: Do not trust that caller is not modifying cases data underfoot.
// The range is safe because the caller cannot modify our copy of the len
// and each iteration makes its own copy of the value c.
// selectgo implements the select statement.
//
// cas0 points to an array of type [ncases]scase, and order0 points to
-// an array of type [2*ncases]uint16. Both reside on the goroutine's
-// stack (regardless of any escaping in selectgo).
+// an array of type [2*ncases]uint16 where ncases must be <= 65536.
+// Both reside on the goroutine's stack (regardless of any escaping in
+// selectgo).
//
// selectgo returns the index of the chosen scase, which matches the
// ordinal position of its respective select{recv,send,default} call.
print("select: cas0=", cas0, "\n")
}
+ // NOTE: In order to maintain a lean stack size, the number of scases
+ // is capped at 65536.
cas1 := (*[1 << 16]scase)(unsafe.Pointer(cas0))
order1 := (*[1 << 17]uint16)(unsafe.Pointer(order0))