]> Cypherpunks repositories - gostls13.git/commitdiff
replace non-blocking send, receive syntax with select
authorRuss Cox <rsc@golang.org>
Mon, 31 Jan 2011 23:36:28 +0000 (18:36 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 31 Jan 2011 23:36:28 +0000 (18:36 -0500)
R=golang-dev, nigeltao, niemeyer, r
CC=golang-dev
https://golang.org/cl/4079053

27 files changed:
src/pkg/compress/flate/deflate_test.go
src/pkg/exp/draw/x11/conn.go
src/pkg/fmt/print.go
src/pkg/fmt/scan.go
src/pkg/net/fd.go
src/pkg/net/server_test.go
src/pkg/netchan/common.go
src/pkg/netchan/import.go
src/pkg/os/inotify/inotify_linux.go
src/pkg/path/path_test.go
src/pkg/rpc/client.go
src/pkg/rpc/server_test.go
src/pkg/time/sleep_test.go
src/pkg/time/tick.go
src/pkg/time/tick_test.go
test/chan/nonblock.go
test/chan/perm.go
test/closedchan.go
test/errchk
test/fixedbugs/bug016.go
test/fixedbugs/bug069.go
test/fixedbugs/bug081.go
test/fixedbugs/bug196.go
test/fixedbugs/bug234.go
test/fixedbugs/bug242.go
test/golden.out
test/named1.go

index 3db955609d7eb85c1b9ea2904b74ba0a92f5407e..68dcd7bcc52240041af0c25fec14a87124b9512a 100644 (file)
@@ -116,9 +116,16 @@ func (b *syncBuffer) Read(p []byte) (n int, err os.Error) {
        panic("unreachable")
 }
 
+func (b *syncBuffer) signal() {
+       select {
+       case b.ready <- true:
+       default:
+       }
+}
+
 func (b *syncBuffer) Write(p []byte) (n int, err os.Error) {
        n, err = b.buf.Write(p)
-       _ = b.ready <- true
+       b.signal()
        return
 }
 
@@ -128,12 +135,12 @@ func (b *syncBuffer) WriteMode() {
 
 func (b *syncBuffer) ReadMode() {
        b.mu.Unlock()
-       _ = b.ready <- true
+       b.signal()
 }
 
 func (b *syncBuffer) Close() os.Error {
        b.closed = true
-       _ = b.ready <- true
+       b.signal()
        return nil
 }
 
index da2181536fb2192dbc2d74ca28096e722383f72a..e28fb217065dfcf470c1a7ecc5198f0cb7917835 100644 (file)
@@ -122,10 +122,13 @@ func (c *conn) writeSocket() {
 func (c *conn) Screen() draw.Image { return c.img }
 
 func (c *conn) FlushImage() {
-       // We do the send (the <- operator) in an expression context, rather than in
-       // a statement context, so that it does not block, and fails if the buffered
-       // channel is full (in which case there already is a flush request pending).
-       _ = c.flush <- false
+       select {
+       case c.flush <- false:
+               // Flush notification sent.
+       default:
+               // Could not send.
+               // Flush notification must be pending already.
+       }
 }
 
 func (c *conn) Close() os.Error {
index 96029a8789f12c8a405030e47748e46abc4bc3ce..d6dc8eb3daa59b9d499e543f3697dc6f406a5819 100644 (file)
@@ -74,15 +74,42 @@ type pp struct {
        fmt     fmt
 }
 
-// A leaky bucket of reusable pp structures.
-var ppFree = make(chan *pp, 100)
+// A cache holds a set of reusable objects.
+// The buffered channel holds the currently available objects.
+// If more are needed, the cache creates them by calling new.
+type cache struct {
+       saved chan interface{}
+       new   func() interface{}
+}
+
+func (c *cache) put(x interface{}) {
+       select {
+       case c.saved <- x:
+               // saved in cache
+       default:
+               // discard
+       }
+}
 
-// Allocate a new pp struct.  Probably can grab the previous one from ppFree.
-func newPrinter() *pp {
-       p, ok := <-ppFree
-       if !ok {
-               p = new(pp)
+func (c *cache) get() interface{} {
+       select {
+       case x := <-c.saved:
+               return x // reused from cache
+       default:
+               return c.new()
        }
+       panic("not reached")
+}
+
+func newCache(f func() interface{}) *cache {
+       return &cache{make(chan interface{}, 100), f}
+}
+
+var ppFree = newCache(func() interface{} { return new(pp) })
+
+// Allocate a new pp struct or grab a cached one.
+func newPrinter() *pp {
+       p := ppFree.get().(*pp)
        p.fmt.init(&p.buf)
        return p
 }
@@ -94,7 +121,7 @@ func (p *pp) free() {
                return
        }
        p.buf.Reset()
-       _ = ppFree <- p
+       ppFree.put(p)
 }
 
 func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent }
index ebbb17155e4a9de0f323373a08f53ba5f7e6a838..a408c42aaf1b623341b1e77f86368fd61c49121c 100644 (file)
@@ -303,15 +303,11 @@ func (r *readRune) ReadRune() (rune int, size int, err os.Error) {
 }
 
 
-// A leaky bucket of reusable ss structures.
-var ssFree = make(chan *ss, 100)
+var ssFree = newCache(func() interface{} { return new(ss) })
 
-// Allocate a new ss struct.  Probably can grab the previous one from ssFree.
+// Allocate a new ss struct or grab a cached one.
 func newScanState(r io.Reader, nlIsSpace bool) *ss {
-       s, ok := <-ssFree
-       if !ok {
-               s = new(ss)
-       }
+       s := ssFree.get().(*ss)
        if rr, ok := r.(readRuner); ok {
                s.rr = rr
        } else {
@@ -333,7 +329,7 @@ func (s *ss) free() {
        }
        s.buf.Reset()
        s.rr = nil
-       _ = ssFree <- s
+       ssFree.put(s)
 }
 
 // skipSpace skips spaces and maybe newlines.
index 896178f18efeff4a7b02be082b1f55d64cf5fe55..2ba9296f315d321a306a79affec600f92f4abe3e 100644 (file)
@@ -220,11 +220,16 @@ func (s *pollServer) Run() {
                                nn, _ = s.pr.Read(scratch[0:])
                        }
                        // Read from channels
-                       for fd, ok := <-s.cr; ok; fd, ok = <-s.cr {
-                               s.AddFD(fd, 'r')
-                       }
-                       for fd, ok := <-s.cw; ok; fd, ok = <-s.cw {
-                               s.AddFD(fd, 'w')
+               Update:
+                       for {
+                               select {
+                               case fd := <-s.cr:
+                                       s.AddFD(fd, 'r')
+                               case fd := <-s.cw:
+                                       s.AddFD(fd, 'w')
+                               default:
+                                       break Update
+                               }
                        }
                } else {
                        netfd := s.LookupFD(fd, mode)
index 543227f7d12e13a5271b033aaa5144a25064e36b..3dda500e585608d7765f7efc76b79ee02f5883d1 100644 (file)
@@ -140,13 +140,16 @@ func runPacket(t *testing.T, network, addr string, listening chan<- string, done
        listening <- c.LocalAddr().String()
        c.SetReadTimeout(10e6) // 10ms
        var buf [1000]byte
+Run:
        for {
                n, addr, err := c.ReadFrom(buf[0:])
                if e, ok := err.(Error); ok && e.Timeout() {
-                       if done <- 1 {
-                               break
+                       select {
+                       case done <- 1:
+                               break Run
+                       default:
+                               continue Run
                        }
-                       continue
                }
                if err != nil {
                        break
index 56c0b25199fa7443ef89087e141774efb0035b96..6c085484e5eb4abcf5a71478891260341ec09d5c 100644 (file)
@@ -256,7 +256,10 @@ func (nch *netChan) send(val reflect.Value) {
                nch.sendCh = make(chan reflect.Value, nch.size)
                go nch.sender()
        }
-       if ok := nch.sendCh <- val; !ok {
+       select {
+       case nch.sendCh <- val:
+               // ok
+       default:
                // TODO: should this be more resilient?
                panic("netchan: remote sender sent more values than allowed")
        }
@@ -318,8 +321,11 @@ func (nch *netChan) acked() {
        if nch.dir != Send {
                panic("recv on wrong direction of channel")
        }
-       if ok := nch.ackCh <- true; !ok {
-               panic("netchan: remote receiver sent too many acks")
+       select {
+       case nch.ackCh <- true:
+               // ok
+       default:
                // TODO: should this be more resilient?
+               panic("netchan: remote receiver sent too many acks")
        }
 }
index a694fb41f6dcbb6a05a457d9658c01ed2b0d3fcb..d1e9bbd4063a20516a8b456d03ecb202836a1497 100644 (file)
@@ -91,11 +91,13 @@ func (imp *Importer) run() {
                        }
                        if err.Error != "" {
                                impLog("response error:", err.Error)
-                               if sent := imp.errors <- os.ErrorString(err.Error); !sent {
+                               select {
+                               case imp.errors <- os.ErrorString(err.Error):
+                                       continue // errors are not acknowledged
+                               default:
                                        imp.shutdown()
                                        return
                                }
-                               continue // errors are not acknowledged.
                        }
                case payClosed:
                        nch := imp.getChan(hdr.Id, false)
index 1e74c7fbc536309a88ff41be831a4ada6483bfec..9d7a074424dbd992bd752b4c2dc5a338c9879378 100644 (file)
@@ -153,7 +153,11 @@ func (w *Watcher) readEvents() {
        for {
                n, errno = syscall.Read(w.fd, buf[0:])
                // See if there is a message on the "done" channel
-               _, done := <-w.done
+               var done bool
+               select {
+               case done = <-w.done:
+               default:
+               }
 
                // If EOF or a "done" message is received
                if n == 0 || done {
index 6b4be07a958256d13029d8d9d569497ad55dfc4c..ab0b48ad6ad94a3cf470104c84340cf5119e9a6b 100644 (file)
@@ -256,8 +256,11 @@ func TestWalk(t *testing.T) {
        // 2) handle errors, expect none
        errors := make(chan os.Error, 64)
        Walk(tree.name, v, errors)
-       if err, ok := <-errors; ok {
+       select {
+       case err := <-errors:
                t.Errorf("no error expected, found: %s", err)
+       default:
+               // ok
        }
        checkMarks(t)
 
@@ -276,14 +279,21 @@ func TestWalk(t *testing.T) {
                errors = make(chan os.Error, 64)
                os.Chmod(Join(tree.name, tree.entries[1].name), 0)
                Walk(tree.name, v, errors)
+       Loop:
                for i := 1; i <= 2; i++ {
-                       if _, ok := <-errors; !ok {
+                       select {
+                       case <-errors:
+                               // ok
+                       default:
                                t.Errorf("%d. error expected, none found", i)
-                               break
+                               break Loop
                        }
                }
-               if err, ok := <-errors; ok {
+               select {
+               case err := <-errors:
                        t.Errorf("only two errors expected, found 3rd: %v", err)
+               default:
+                       // ok
                }
                // the inaccessible subtrees were marked manually
                checkMarks(t)
index 601c49715b351b0e95ae6aae604d23b756d8f454..6f028c10d968eb40f8b135d4bb60121b7aceda95 100644 (file)
@@ -58,7 +58,7 @@ func (client *Client) send(c *Call) {
        if client.shutdown != nil {
                c.Error = client.shutdown
                client.mutex.Unlock()
-               _ = c.Done <- c // do not block
+               c.done()
                return
        }
        c.seq = client.seq
@@ -102,16 +102,14 @@ func (client *Client) input() {
                        // Empty strings should turn into nil os.Errors
                        c.Error = nil
                }
-               // We don't want to block here.  It is the caller's responsibility to make
-               // sure the channel has enough buffer space. See comment in Go().
-               _ = c.Done <- c // do not block
+               c.done()
        }
        // Terminate pending calls.
        client.mutex.Lock()
        client.shutdown = err
        for _, call := range client.pending {
                call.Error = err
-               _ = call.Done <- call // do not block
+               call.done()
        }
        client.mutex.Unlock()
        if err != os.EOF || !client.closing {
@@ -119,6 +117,16 @@ func (client *Client) input() {
        }
 }
 
+func (call *Call) done() {
+       select {
+       case call.Done <- call:
+               // ok
+       default:
+               // We don't want to block here.  It is the caller's responsibility to make
+               // sure the channel has enough buffer space. See comment in Go().
+       }
+}
+
 // NewClient returns a new Client to handle requests to the
 // set of services at the other end of the connection.
 func NewClient(conn io.ReadWriteCloser) *Client {
@@ -233,7 +241,7 @@ func (client *Client) Go(serviceMethod string, args interface{}, reply interface
        c.Done = done
        if client.shutdown != nil {
                c.Error = client.shutdown
-               _ = c.Done <- c // do not block
+               c.done()
                return c
        }
        client.send(c)
index 355d51ce46b828c99729c9d3cc285c6fa70a677f..67b8762fa56ee4b75bba2d6763ba617d98e8df63 100644 (file)
@@ -364,14 +364,12 @@ func TestSendDeadlock(t *testing.T) {
                testSendDeadlock(client)
                done <- true
        }()
-       for i := 0; i < 50; i++ {
-               time.Sleep(100 * 1e6)
-               _, ok := <-done
-               if ok {
-                       return
-               }
+       select {
+       case <-done:
+               return
+       case <-time.After(5e9):
+               t.Fatal("deadlock")
        }
-       t.Fatal("deadlock")
 }
 
 func testSendDeadlock(client *Client) {
index 4007db561a674e0e2e782ae3eb109e5968356072..8bf599c3e1a96d3dc5a893331692b10efa0a43a7 100644 (file)
@@ -120,10 +120,12 @@ func TestAfterStop(t *testing.T) {
                t.Fatalf("failed to stop event 1")
        }
        <-c2
-       _, ok0 := <-t0.C
-       _, ok1 := <-c1
-       if ok0 || ok1 {
-               t.Fatalf("events were not stopped")
+       select {
+       case <-t0.C:
+               t.Fatalf("event 0 was not stopped")
+       case <-c1:
+               t.Fatalf("event 1 was not stopped")
+       default:
        }
        if t1.Stop() {
                t.Fatalf("Stop returned true twice")
index ddd72727027d5938a0bcbb6fa22a1ca2bc3acd23..6c21bf19b92c9a091bf07a9b99bc53ec801ab0a6 100644 (file)
@@ -22,8 +22,12 @@ type Ticker struct {
 
 // Stop turns off a ticker.  After Stop, no more ticks will be sent.
 func (t *Ticker) Stop() {
-       // Make it non-blocking so multiple Stops don't block.
-       _ = t.shutdown <- true
+       select {
+       case t.shutdown <- true:
+               // ok
+       default:
+               // Stop in progress already
+       }
 }
 
 // Tick is a convenience wrapper for NewTicker providing access to the ticking
@@ -106,7 +110,8 @@ func tickerLoop() {
                        // that need it and determining the next wake time.
                        // TODO(r): list should be sorted in time order.
                        for t := tickers; t != nil; t = t.next {
-                               if _, ok := <-t.shutdown; ok {
+                               select {
+                               case <-t.shutdown:
                                        // Ticker is done; remove it from list.
                                        if prev == nil {
                                                tickers = t.next
@@ -114,6 +119,7 @@ func tickerLoop() {
                                                prev.next = t.next
                                        }
                                        continue
+                               default:
                                }
                                if t.nextTick <= now {
                                        if len(t.c) == 0 {
index f2304a14e33cb5e0e7c7a0192014a414dc3d1fc3..4dcb63956b2ce1c8bcd4563ce86316d30ffdc108 100644 (file)
@@ -29,9 +29,11 @@ func TestTicker(t *testing.T) {
        }
        // Now test that the ticker stopped
        Sleep(2 * Delta)
-       _, received := <-ticker.C
-       if received {
+       select {
+       case <-ticker.C:
                t.Fatal("Ticker did not shut down")
+       default:
+               // ok
        }
 }
 
index 52f04bfb12f53c4d87c1c653616bfcd1f5a094f6..33afb3291652b11f93da64001ba36d85a84c5cb9 100644 (file)
@@ -76,7 +76,6 @@ func main() {
        var i64 int64
        var b bool
        var s string
-       var ok bool
 
        var sync = make(chan bool)
 
@@ -86,35 +85,45 @@ func main() {
                cb := make(chan bool, buffer)
                cs := make(chan string, buffer)
 
-               i32, ok = <-c32
-               if ok {
+               select {
+               case i32 = <-c32:
                        panic("blocked i32sender")
+               default:
                }
 
-               i64, ok = <-c64
-               if ok {
+               select {
+               case i64 = <-c64:
                        panic("blocked i64sender")
+               default:
                }
 
-               b, ok = <-cb
-               if ok {
+               select {
+               case b = <-cb:
                        panic("blocked bsender")
+               default:
                }
 
-               s, ok = <-cs
-               if ok {
+               select {
+               case s = <-cs:
                        panic("blocked ssender")
+               default:
                }
 
                go i32receiver(c32, sync)
                try := 0
-               for !(c32 <- 123) {
-                       try++
-                       if try > maxTries {
-                               println("i32receiver buffer=", buffer)
-                               panic("fail")
+       Send32:
+               for {
+                       select {
+                       case c32 <- 123:
+                               break Send32
+                       default:
+                               try++
+                               if try > maxTries {
+                                       println("i32receiver buffer=", buffer)
+                                       panic("fail")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                <-sync
 
@@ -123,13 +132,19 @@ func main() {
                        <-sync
                }
                try = 0
-               for i32, ok = <-c32; !ok; i32, ok = <-c32 {
-                       try++
-                       if try > maxTries {
-                               println("i32sender buffer=", buffer)
-                               panic("fail")
+       Recv32:
+               for {
+                       select {
+                       case i32 = <-c32:
+                               break Recv32
+                       default:
+                               try++
+                               if try > maxTries {
+                                       println("i32sender buffer=", buffer)
+                                       panic("fail")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                if i32 != 234 {
                        panic("i32sender value")
@@ -140,12 +155,18 @@ func main() {
 
                go i64receiver(c64, sync)
                try = 0
-               for !(c64 <- 123456) {
-                       try++
-                       if try > maxTries {
-                               panic("i64receiver")
+       Send64:
+               for {
+                       select {
+                       case c64 <- 123456:
+                               break Send64
+                       default:
+                               try++
+                               if try > maxTries {
+                                       panic("i64receiver")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                <-sync
 
@@ -154,12 +175,18 @@ func main() {
                        <-sync
                }
                try = 0
-               for i64, ok = <-c64; !ok; i64, ok = <-c64 {
-                       try++
-                       if try > maxTries {
-                               panic("i64sender")
+       Recv64:
+               for {
+                       select {
+                       case i64 = <-c64:
+                               break Recv64
+                       default:
+                               try++
+                               if try > maxTries {
+                                       panic("i64sender")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                if i64 != 234567 {
                        panic("i64sender value")
@@ -170,12 +197,18 @@ func main() {
 
                go breceiver(cb, sync)
                try = 0
-               for !(cb <- true) {
-                       try++
-                       if try > maxTries {
-                               panic("breceiver")
+       SendBool:
+               for {
+                       select {
+                       case cb <- true:
+                               break SendBool
+                       default:
+                               try++
+                               if try > maxTries {
+                                       panic("breceiver")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                <-sync
 
@@ -184,12 +217,18 @@ func main() {
                        <-sync
                }
                try = 0
-               for b, ok = <-cb; !ok; b, ok = <-cb {
-                       try++
-                       if try > maxTries {
-                               panic("bsender")
+       RecvBool:
+               for {
+                       select {
+                       case b = <-cb:
+                               break RecvBool
+                       default:
+                               try++
+                               if try > maxTries {
+                                       panic("bsender")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                if !b {
                        panic("bsender value")
@@ -200,12 +239,18 @@ func main() {
 
                go sreceiver(cs, sync)
                try = 0
-               for !(cs <- "hello") {
-                       try++
-                       if try > maxTries {
-                               panic("sreceiver")
+       SendString:
+               for {
+                       select {
+                       case cs <- "hello":
+                               break SendString
+                       default:
+                               try++
+                               if try > maxTries {
+                                       panic("sreceiver")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                <-sync
 
@@ -214,12 +259,18 @@ func main() {
                        <-sync
                }
                try = 0
-               for s, ok = <-cs; !ok; s, ok = <-cs {
-                       try++
-                       if try > maxTries {
-                               panic("ssender")
+       RecvString:
+               for {
+                       select {
+                       case s = <-cs:
+                               break RecvString
+                       default:
+                               try++
+                               if try > maxTries {
+                                       panic("ssender")
+                               }
+                               sleep()
                        }
-                       sleep()
                }
                if s != "hello again" {
                        panic("ssender value")
index d08c035193de0366005b370d695c7b5558be3cdc..c725829d13293aa8817b6ee2f239d8788728910e 100644 (file)
@@ -9,49 +9,46 @@ package main
 var (
        cr <-chan int
        cs chan<- int
-       c chan int
+       c  chan int
 )
 
 func main() {
-       cr = c          // ok
-       cs = c          // ok
-       c = cr          // ERROR "illegal types|incompatible|cannot"
-       c = cs          // ERROR "illegal types|incompatible|cannot"
-       cr = cs // ERROR "illegal types|incompatible|cannot"
-       cs = cr // ERROR "illegal types|incompatible|cannot"
-
-       c <- 0          // ok
-       ok := c <- 0    // ok
-       _ = ok
-       <-c             // ok
-       x, ok := <-c    // ok
-       _, _ = x, ok
-
-       cr <- 0 // ERROR "send"
-       ok = cr <- 0    // ERROR "send"
-       _ = ok
-       <-cr            // ok
-       x, ok = <-cr    // ok
-       _, _ = x, ok
-
-       cs <- 0 // ok
-       ok = cs <- 0    // ok
-       _ = ok
-       <-cs            // ERROR "receive"
-       x, ok = <-cs    // ERROR "receive"
-       _, _ = x, ok
+       cr = c  // ok
+       cs = c  // ok
+       c = cr  // ERROR "illegal types|incompatible|cannot"
+       c = cs  // ERROR "illegal types|incompatible|cannot"
+       cr = cs // ERROR "illegal types|incompatible|cannot"
+       cs = cr // ERROR "illegal types|incompatible|cannot"
+
+       c <- 0 // ok
+       <-c    // ok
+       //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+       //      x, ok := <-c    // ok
+       //      _, _ = x, ok
+
+       cr <- 0 // ERROR "send"
+       <-cr    // ok
+       //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+       //      x, ok = <-cr    // ok
+       //      _, _ = x, ok
+
+       cs <- 0 // ok
+       <-cs    // ERROR "receive"
+       ////TODO(rsc): uncomment when this syntax is valid for receive+check closed
+       ////    x, ok = <-cs    // ERROR "receive"
+       ////    _, _ = x, ok
 
        select {
-       case c <- 0:    // ok
-       case x := <-c:  // ok
+       case c <- 0: // ok
+       case x := <-c: // ok
                _ = x
 
-       case cr <- 0:   // ERROR "send"
-       case x := <-cr: // ok
+       case cr <- 0: // ERROR "send"
+       case x := <-cr: // ok
                _ = x
 
-       case cs <- 0:   // ok
-       case x := <-cs: // ERROR "receive"
+       case cs <- 0: // ok
+       case x := <-cs: // ERROR "receive"
                _ = x
        }
 }
index 8126d5a4e4c71ade746f8e836d7f25451cf19d73..46d9d0f5d211effcf6a34cd4e06dc034b6b93abc 100644 (file)
@@ -21,14 +21,21 @@ type Chan interface {
        Impl() string
 }
 
-// direct channel operations
+// direct channel operations when possible
 type XChan chan int
+
 func (c XChan) Send(x int) {
        c <- x
 }
 
 func (c XChan) Nbsend(x int) bool {
-       return c <- x
+       select {
+       case c <- x:
+               return true
+       default:
+               return false
+       }
+       panic("nbsend")
 }
 
 func (c XChan) Recv() int {
@@ -36,8 +43,13 @@ func (c XChan) Recv() int {
 }
 
 func (c XChan) Nbrecv() (int, bool) {
-       x, ok := <-c
-       return x, ok
+       select {
+       case x := <-c:
+               return x, true
+       default:
+               return 0, false
+       }
+       panic("nbrecv")
 }
 
 func (c XChan) Close() {
@@ -54,6 +66,7 @@ func (c XChan) Impl() string {
 
 // indirect operations via select
 type SChan chan int
+
 func (c SChan) Send(x int) {
        select {
        case c <- x:
@@ -62,10 +75,10 @@ func (c SChan) Send(x int) {
 
 func (c SChan) Nbsend(x int) bool {
        select {
-       case c <- x:
-               return true
        default:
                return false
+       case c <- x:
+               return true
        }
        panic("nbsend")
 }
@@ -80,10 +93,10 @@ func (c SChan) Recv() int {
 
 func (c SChan) Nbrecv() (int, bool) {
        select {
-       case x := <-c:
-               return x, true
        default:
                return 0, false
+       case x := <-c:
+               return x, true
        }
        panic("nbrecv")
 }
@@ -100,6 +113,62 @@ func (c SChan) Impl() string {
        return "(select)"
 }
 
+// indirect operations via larger selects
+var dummy = make(chan bool)
+
+type SSChan chan int
+
+func (c SSChan) Send(x int) {
+       select {
+       case c <- x:
+       case <-dummy:
+       }
+}
+
+func (c SSChan) Nbsend(x int) bool {
+       select {
+       default:
+               return false
+       case <-dummy:
+       case c <- x:
+               return true
+       }
+       panic("nbsend")
+}
+
+func (c SSChan) Recv() int {
+       select {
+       case <-dummy:
+       case x := <-c:
+               return x
+       }
+       panic("recv")
+}
+
+func (c SSChan) Nbrecv() (int, bool) {
+       select {
+       case <-dummy:
+       default:
+               return 0, false
+       case x := <-c:
+               return x, true
+       }
+       panic("nbrecv")
+}
+
+func (c SSChan) Close() {
+       close(c)
+}
+
+func (c SSChan) Closed() bool {
+       return closed(c)
+}
+
+func (c SSChan) Impl() string {
+       return "(select)"
+}
+
+
 func shouldPanic(f func()) {
        defer func() {
                if recover() == nil {
@@ -137,7 +206,7 @@ func test1(c Chan) {
        }
 
        // send should work with ,ok too: sent a value without blocking, so ok == true.
-       shouldPanic(func(){c.Nbsend(1)})
+       shouldPanic(func() { c.Nbsend(1) })
 
        // the value should have been discarded.
        if x := c.Recv(); x != 0 {
@@ -145,7 +214,7 @@ func test1(c Chan) {
        }
 
        // similarly Send.
-       shouldPanic(func(){c.Send(2)})
+       shouldPanic(func() { c.Send(2) })
        if x := c.Recv(); x != 0 {
                println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
        }
@@ -195,9 +264,12 @@ func closedasync() chan int {
 func main() {
        test1(XChan(closedsync()))
        test1(SChan(closedsync()))
+       test1(SSChan(closedsync()))
 
        testasync1(XChan(closedasync()))
        testasync1(SChan(closedasync()))
+       testasync1(SSChan(closedasync()))
        testasync2(XChan(closedasync()))
        testasync2(SChan(closedasync()))
+       testasync2(SSChan(closedasync()))
 }
index b0edd7a6b03975c74730cda83407758deebce8f0..fbb021ce41768cb6e1a49c954da39bb923e70724 100755 (executable)
@@ -73,6 +73,7 @@ sub chk {
        my @match;
        foreach my $src (@{$src{$file}}) {
                $line++;
+               next if $src =~ m|////|;  # double comment disables ERROR
                next unless $src =~ m|// (GC_)?ERROR (.*)|;
                $regexp = $2;
                if($regexp !~ /^"([^"]*)"/) {
index 461bcf82ac44c67a153332f2a0cdfa01a4c7dd5f..1cdd8df08423faf64ceeb098057024b9d0babf49 100644 (file)
@@ -1,4 +1,4 @@
-// ! $G $D/$F.go
+// errchk $G -e $D/$F.go
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -7,8 +7,8 @@
 package main
 
 func main() {
-       var i int = 100;
-       i = i << -3;  // BUG: should not compile (negative shift)
+       var i int = 100
+       i = i << -3 // ERROR "overflows"
 }
 
 /*
index d6796cd72be19cdf4427c31208643f519d028633..bf73163134d709cb41b4fdb97f0add621cd54bb0 100644 (file)
@@ -6,15 +6,16 @@
 
 package main
 
-func main(){
-       c := make(chan int);
-       ok := false;
-       var i int;
-
-       i, ok = <-c;  // works
-       _, _ = i, ok;
-
-       ca := new([2]chan int);
-       i, ok = <-(ca[0]);  // fails: c.go:11: bad shape across assignment - cr=1 cl=2
-       _, _ = i, ok;
+func main() {
+       //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+       //      c := make(chan int);
+       //      ok := false;
+       //      var i int;
+       //
+       //      i, ok = <-c;  // works
+       //      _, _ = i, ok;
+       //
+       //      ca := new([2]chan int);
+       //      i, ok = <-(ca[0]);  // fails: c.go:11: bad shape across assignment - cr=1 cl=2
+       //      _, _ = i, ok;
 }
index ccb3699534345d6bacdea054a481805059731e25..8d3d538c8f12dedc153fefa5a38f2fedf61ad168 100644 (file)
@@ -1,12 +1,12 @@
-// ! $G $D/$F.go
+// errchk $G $D/$F.go
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package main   
-       
-const x x = 2;
+package main
+
+const x x = 2 // ERROR "loop"
 
 /*
 bug081.go:3: first constant must evaluate an expression
index ea8ab0dc193c71e82686a814d0c8fbd11e36b2bb..8cb9c9990d9d3bf9d2cf5070a0b569278ea9fa77 100644 (file)
@@ -13,11 +13,12 @@ var i int
 func multi() (int, int) { return 1, 2 }
 
 func xxx() {
-       var c chan int
-       x, ok := <-c
+       //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+       //      var c chan int
+       //      x, ok := <-c
 
        var m map[int]int
-       x, ok = m[1]
+       x, ok := m[1]
 
        var i interface{}
        var xx int
index b806ca64e98f2cad5ba97cb580afff2dd210fc91..9affad043027a3e6cde34f0a05fcc7c5d515d056 100644 (file)
@@ -7,16 +7,17 @@
 package main
 
 func main() {
-       c := make(chan int, 1)
-       c <- 100
-       x, ok := <-c
-       if x != 100 || !ok {
-               println("x=", x, " ok=", ok, " want 100, true")
-               panic("fail")
-       }
-       x, ok = <-c
-       if x != 0 || ok {
-               println("x=", x, " ok=", ok, " want 0, false")
-               panic("fail")
-       }
+       //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+       //      c := make(chan int, 1)
+       //      c <- 100
+       //      x, ok := <-c
+       //      if x != 100 || !ok {
+       //              println("x=", x, " ok=", ok, " want 100, true")
+       //              panic("fail")
+       //      }
+       //      x, ok = <-c
+       //      if x != 0 || ok {
+       //              println("x=", x, " ok=", ok, " want 0, false")
+       //              panic("fail")
+       //      }
 }
index 5c21eaaf0084c36ce24b71f1b037457bcc961057..ad1cef8df4302b49baa0f30cb699990b74283241 100644 (file)
@@ -101,10 +101,13 @@ func main() {
 
        c := make(chan byte, 1)
        c <- 'C'
+       //TODO(rsc): uncomment when this syntax is valid for receive+check closed
        // 15          16
-       *f(), p1 = <-e1(c, 16)
+       //      *f(), p1 = <-e1(c, 16)
+       *f(), p1 = <-e1(c, 16), true // delete uncommenting above
        // 17          18
-       *f(), p2 = <-e1(c, 18)
+       //      *f(), p2 = <-e1(c, 18)
+       *f(), p2, _ = 0, false, e1(c, 18) // delete when uncommenting above
        a[17] += '0'
        if !p1 || p2 {
                println("bad chan check", i, p1, p2)
index 83e8327a517505254fa8520dccc7fee4ee180e3d..425771b4afe4f076caba0932dfb84905381d488d 100644 (file)
@@ -123,9 +123,6 @@ panic: interface conversion: *main.S is not main.I2: missing method Name
 
 == fixedbugs/
 
-=========== fixedbugs/bug016.go
-fixedbugs/bug016.go:11: constant -3 overflows uint
-
 =========== fixedbugs/bug027.go
 hi
 0 44444
@@ -148,9 +145,6 @@ inner loop top i 0
 do break
 broke
 
-=========== fixedbugs/bug081.go
-fixedbugs/bug081.go:9: typechecking loop
-
 =========== fixedbugs/bug093.go
 M
 
index 600e502f9e8f31c8926a5665579483cd3f3c85a6..1776313f05cea2de56c2cba1e61b7de4d5635d4b 100644 (file)
@@ -43,12 +43,9 @@ func main() {
        _, b = m[2] // ERROR "cannot .* bool.*type Bool"
        m[2] = 1, b // ERROR "cannot use.*type Bool.*as type bool"
 
-       b = c <- 1 // ERROR "cannot use.*type bool.*type Bool"
-       _ = b
-       asBool(c <- 1) // ERROR "cannot use.*type bool.*as type Bool"
-
-       _, b = <-c // ERROR "cannot .* bool.*type Bool"
-       _ = b
+       ////TODO(rsc): uncomment when this syntax is valid for receive+check closed
+       ////    _, b = <-c // ERROR "cannot .* bool.*type Bool"
+       ////    _ = b
 
        var inter interface{}
        _, b = inter.(Map) // ERROR "cannot .* bool.*type Bool"