aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgo/go/net/fd_select.go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgo/go/net/fd_select.go')
-rw-r--r--gcc-4.9/libgo/go/net/fd_select.go182
1 files changed, 182 insertions, 0 deletions
diff --git a/gcc-4.9/libgo/go/net/fd_select.go b/gcc-4.9/libgo/go/net/fd_select.go
new file mode 100644
index 000000000..4103c57e2
--- /dev/null
+++ b/gcc-4.9/libgo/go/net/fd_select.go
@@ -0,0 +1,182 @@
+// Copyright 2010 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.
+
+// Waiting for FDs via select(2).
+
+package net
+
+import (
+ "errors"
+ "os"
+ "syscall"
+)
+
+type pollster struct {
+ readFds, writeFds, repeatFds *syscall.FdSet
+ maxFd int
+ readyReadFds, readyWriteFds *syscall.FdSet
+ nReady int
+ lastFd int
+ closed bool
+}
+
+func newpollster() (p *pollster, err error) {
+ p = new(pollster)
+ p.readFds = new(syscall.FdSet)
+ p.writeFds = new(syscall.FdSet)
+ p.repeatFds = new(syscall.FdSet)
+ p.readyReadFds = new(syscall.FdSet)
+ p.readyWriteFds = new(syscall.FdSet)
+ p.maxFd = -1
+ p.nReady = 0
+ p.lastFd = 0
+ return p, nil
+}
+
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
+ // pollServer is locked.
+
+ if p.closed {
+ return false, errors.New("pollster closed")
+ }
+
+ if mode == 'r' {
+ syscall.FDSet(fd, p.readFds)
+ } else {
+ syscall.FDSet(fd, p.writeFds)
+ }
+
+ if repeat {
+ syscall.FDSet(fd, p.repeatFds)
+ }
+
+ if fd > p.maxFd {
+ p.maxFd = fd
+ }
+
+ return true, nil
+}
+
+func (p *pollster) DelFD(fd int, mode int) bool {
+ // pollServer is locked.
+
+ if p.closed {
+ return false
+ }
+
+ if mode == 'r' {
+ if !syscall.FDIsSet(fd, p.readFds) {
+ print("Select unexpected fd=", fd, " for read\n")
+ return false
+ }
+ syscall.FDClr(fd, p.readFds)
+ } else {
+ if !syscall.FDIsSet(fd, p.writeFds) {
+ print("Select unexpected fd=", fd, " for write\n")
+ return false
+ }
+ syscall.FDClr(fd, p.writeFds)
+ }
+
+ // Doesn't matter if not already present.
+ syscall.FDClr(fd, p.repeatFds)
+
+ // We don't worry about maxFd here.
+
+ return true
+}
+
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
+ if p.nReady == 0 {
+ var timeout *syscall.Timeval
+ var tv syscall.Timeval
+ timeout = nil
+ if nsec > 0 {
+ tv = syscall.NsecToTimeval(nsec)
+ timeout = &tv
+ }
+
+ var n int
+ var e error
+ var tmpReadFds, tmpWriteFds syscall.FdSet
+ for {
+ if p.closed {
+ return -1, 0, errors.New("pollster closed")
+ }
+
+ // Temporary syscall.FdSet's into which the values are copied
+ // because select mutates the values.
+ tmpReadFds = *p.readFds
+ tmpWriteFds = *p.writeFds
+
+ s.Unlock()
+ n, e = syscall.Select(p.maxFd+1, &tmpReadFds, &tmpWriteFds, nil, timeout)
+ s.Lock()
+
+ if e != syscall.EINTR {
+ break
+ }
+ }
+ if e == syscall.EBADF {
+ // Some file descriptor has been closed.
+ tmpReadFds = syscall.FdSet{}
+ tmpWriteFds = syscall.FdSet{}
+ n = 0
+ for i := 0; i < p.maxFd+1; i++ {
+ if syscall.FDIsSet(i, p.readFds) {
+ var s syscall.Stat_t
+ if syscall.Fstat(i, &s) == syscall.EBADF {
+ syscall.FDSet(i, &tmpReadFds)
+ n++
+ }
+ } else if syscall.FDIsSet(i, p.writeFds) {
+ var s syscall.Stat_t
+ if syscall.Fstat(i, &s) == syscall.EBADF {
+ syscall.FDSet(i, &tmpWriteFds)
+ n++
+ }
+ }
+ }
+ } else if e != nil {
+ return -1, 0, os.NewSyscallError("select", e)
+ }
+ if n == 0 {
+ return -1, 0, nil
+ }
+
+ p.nReady = n
+ *p.readyReadFds = tmpReadFds
+ *p.readyWriteFds = tmpWriteFds
+ p.lastFd = 0
+ }
+
+ flag := false
+ for i := p.lastFd; i < p.maxFd+1; i++ {
+ if syscall.FDIsSet(i, p.readyReadFds) {
+ flag = true
+ mode = 'r'
+ syscall.FDClr(i, p.readyReadFds)
+ } else if syscall.FDIsSet(i, p.readyWriteFds) {
+ flag = true
+ mode = 'w'
+ syscall.FDClr(i, p.readyWriteFds)
+ }
+ if flag {
+ if !syscall.FDIsSet(i, p.repeatFds) {
+ p.DelFD(i, mode)
+ }
+ p.nReady--
+ p.lastFd = i
+ return i, mode, nil
+ }
+ }
+
+ // Will not reach here. Just to shut up the compiler.
+ return -1, 0, nil
+}
+
+func (p *pollster) Close() error {
+ p.closed = true
+ return nil
+}