func (ar *AsyncReader) Run() { fd := int(ar.rd.Fd()) cfd := int(ar.rCtrl.Fd()) maxfd := max(fd, cfd) fs := sys.NewFdSet() var cBuf [1]byte if nonblock, _ := sys.GetNonblock(fd); !nonblock { sys.SetNonblock(fd, true) defer sys.SetNonblock(fd, false) } for { fs.Set(fd, cfd) err := sys.Select(maxfd+1, fs, nil, nil, nil) if err != nil { switch err { case syscall.EINTR: continue default: panic(err) } } if fs.IsSet(cfd) { // Consume the written byte ar.rCtrl.Read(cBuf[:]) ar.ackCtrl <- true return } else { r, _, err := ar.bufrd.ReadRune() switch err { case nil: ar.ch <- r case io.EOF: return default: // BUG(xiaq): AsyncReader relies on the undocumented fact // that (*os.File).Read returns an *os.File.PathError e := err.(*os.PathError).Err if e != syscall.EWOULDBLOCK && e != syscall.EAGAIN { panic(err) } } } } }
// Run runs the AsyncReader. It blocks until Quit is called and should be // called in a separate goroutine. func (ar *AsyncReader) Run() { fd := int(ar.rd.Fd()) cfd := int(ar.rCtrl.Fd()) maxfd := max(fd, cfd) fs := sys.NewFdSet() var cBuf [1]byte if nonblock, _ := sys.GetNonblock(fd); !nonblock { sys.SetNonblock(fd, true) defer sys.SetNonblock(fd, false) } for { fs.Set(fd, cfd) err := sys.Select(maxfd+1, fs, nil, nil, nil) if err != nil { switch err { case syscall.EINTR: continue default: ar.errCh <- err return } } if fs.IsSet(cfd) { // Consume the written byte ar.rCtrl.Read(cBuf[:]) <-ar.ctrlCh return } ReadRune: for { r, _, err := ar.bufrd.ReadRune() switch err { case nil: // Logger.Printf("read rune: %q", r) select { case ar.ch <- r: case <-ar.ctrlCh: ar.rCtrl.Read(cBuf[:]) return } case io.EOF: return default: // BUG(xiaq): AsyncReader relies on the undocumented fact // that (*os.File).Read returns an *os.File.PathError patherr, ok := err.(*os.PathError) //.Err if !ok { ar.errCh <- err return } e := patherr.Err if e == syscall.EWOULDBLOCK || e == syscall.EAGAIN { break ReadRune } else { ar.errCh <- err return } } } } }
func (ar *AsyncReader) run() { fd := int(ar.rd.Fd()) cfd := int(ar.rCtrl.Fd()) maxfd := max(fd, cfd) fs := sys.NewFdSet() var cBuf [1]byte defer close(ar.ch) sys.SetNonblock(fd, true) for { fs.Set(fd, cfd) err := sys.Select(maxfd+1, fs, nil, nil, nil) if err != nil { switch err { case syscall.EINTR: continue default: panic(err) } } if fs.IsSet(cfd) { // Consume the written byte ar.rCtrl.Read(cBuf[:]) switch cBuf[0] { case asyncReaderQuit: sys.SetNonblock(fd, false) ar.ackCtrl <- true return case asyncReaderContinue: ar.ackCtrl <- true case asyncReaderStop: sys.SetNonblock(fd, false) ar.ackCtrl <- true Stop: for { ar.rCtrl.Read(cBuf[:]) switch cBuf[0] { case asyncReaderQuit: ar.ackCtrl <- true return case asyncReaderContinue: sys.SetNonblock(fd, true) ar.ackCtrl <- true break Stop case asyncReaderStop: ar.ackCtrl <- true } } } } else { ReadRune: for { r, _, err := ar.bufrd.ReadRune() switch err { case nil: ar.ch <- r case io.EOF: return default: // BUG(xiaq): AsyncReader relies on the undocumented fact // that (*os.File).Read returns an *os.File.PathError e := err.(*os.PathError).Err if e == syscall.EWOULDBLOCK || e == syscall.EAGAIN { break ReadRune } else { panic(err) } } } } } }