1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Waiting for FDs via select(2).
14 type pollster struct {
15 readFds, writeFds, repeatFds *syscall.FdSet
17 readyReadFds, readyWriteFds *syscall.FdSet
22 func newpollster() (p *pollster, err error) {
24 p.readFds = new(syscall.FdSet)
25 p.writeFds = new(syscall.FdSet)
26 p.repeatFds = new(syscall.FdSet)
27 p.readyReadFds = new(syscall.FdSet)
28 p.readyWriteFds = new(syscall.FdSet)
35 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
36 // pollServer is locked.
39 syscall.FDSet(fd, p.readFds)
41 syscall.FDSet(fd, p.writeFds)
45 syscall.FDSet(fd, p.repeatFds)
55 func (p *pollster) DelFD(fd int, mode int) {
56 // pollServer is locked.
59 if !syscall.FDIsSet(fd, p.readFds) {
60 print("Select unexpected fd=", fd, " for read\n")
63 syscall.FDClr(fd, p.readFds)
65 if !syscall.FDIsSet(fd, p.writeFds) {
66 print("Select unexpected fd=", fd, " for write\n")
69 syscall.FDClr(fd, p.writeFds)
72 // Doesn't matter if not already present.
73 syscall.FDClr(fd, p.repeatFds)
75 // We don't worry about maxFd here.
78 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
80 var timeout *syscall.Timeval
81 var tv syscall.Timeval
84 tv = syscall.NsecToTimeval(nsec)
90 var tmpReadFds, tmpWriteFds syscall.FdSet
92 // Temporary syscall.FdSet's into which the values are copied
93 // because select mutates the values.
94 tmpReadFds = *p.readFds
95 tmpWriteFds = *p.writeFds
98 n, e = syscall.Select(p.maxFd+1, &tmpReadFds, &tmpWriteFds, nil, timeout)
101 if e != syscall.EINTR {
105 if e == syscall.EBADF {
106 // Some file descriptor has been closed.
107 tmpReadFds = syscall.FdSet{}
108 tmpWriteFds = syscall.FdSet{}
110 for i := 0; i < p.maxFd+1; i++ {
111 if syscall.FDIsSet(i, p.readFds) {
113 if syscall.Fstat(i, &s) == syscall.EBADF {
114 syscall.FDSet(i, &tmpReadFds)
117 } else if syscall.FDIsSet(i, p.writeFds) {
119 if syscall.Fstat(i, &s) == syscall.EBADF {
120 syscall.FDSet(i, &tmpWriteFds)
126 return -1, 0, os.NewSyscallError("select", e)
133 *p.readyReadFds = tmpReadFds
134 *p.readyWriteFds = tmpWriteFds
139 for i := p.lastFd; i < p.maxFd+1; i++ {
140 if syscall.FDIsSet(i, p.readyReadFds) {
143 syscall.FDClr(i, p.readyReadFds)
144 } else if syscall.FDIsSet(i, p.readyWriteFds) {
147 syscall.FDClr(i, p.readyWriteFds)
150 if !syscall.FDIsSet(i, p.repeatFds) {
159 // Will not reach here. Just to shut up the compiler.
163 func (p *pollster) Close() error {