OSDN Git Service

b9544e96c754d8efc0f2e1bc25c0a4bf98bf6381
[pf3gnuchains/gcc-fork.git] / libgo / go / net / fd_select.go
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.
4
5 // Waiting for FDs via select(2).
6
7 package net
8
9 import (
10         "os"
11         "syscall"
12 )
13
14 type pollster struct {
15         readFds, writeFds, repeatFds *syscall.FdSet
16         maxFd                        int
17         readyReadFds, readyWriteFds  *syscall.FdSet
18         nReady                       int
19         lastFd                       int
20 }
21
22 func newpollster() (p *pollster, err error) {
23         p = new(pollster)
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)
29         p.maxFd = -1
30         p.nReady = 0
31         p.lastFd = 0
32         return p, nil
33 }
34
35 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
36         // pollServer is locked.
37
38         if mode == 'r' {
39                 syscall.FDSet(fd, p.readFds)
40         } else {
41                 syscall.FDSet(fd, p.writeFds)
42         }
43
44         if repeat {
45                 syscall.FDSet(fd, p.repeatFds)
46         }
47
48         if fd > p.maxFd {
49                 p.maxFd = fd
50         }
51
52         return true, nil
53 }
54
55 func (p *pollster) DelFD(fd int, mode int) {
56         // pollServer is locked.
57
58         if mode == 'r' {
59                 if !syscall.FDIsSet(fd, p.readFds) {
60                         print("Select unexpected fd=", fd, " for read\n")
61                         return
62                 }
63                 syscall.FDClr(fd, p.readFds)
64         } else {
65                 if !syscall.FDIsSet(fd, p.writeFds) {
66                         print("Select unexpected fd=", fd, " for write\n")
67                         return
68                 }
69                 syscall.FDClr(fd, p.writeFds)
70         }
71
72         // Doesn't matter if not already present.
73         syscall.FDClr(fd, p.repeatFds)
74
75         // We don't worry about maxFd here.
76 }
77
78 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
79         if p.nReady == 0 {
80                 var timeout *syscall.Timeval
81                 var tv syscall.Timeval
82                 timeout = nil
83                 if nsec > 0 {
84                         tv = syscall.NsecToTimeval(nsec)
85                         timeout = &tv
86                 }
87
88                 var n, e int
89                 var tmpReadFds, tmpWriteFds syscall.FdSet
90                 for {
91                         // Temporary syscall.FdSet's into which the values are copied
92                         // because select mutates the values.
93                         tmpReadFds = *p.readFds
94                         tmpWriteFds = *p.writeFds
95
96                         s.Unlock()
97                         n, e = syscall.Select(p.maxFd+1, &tmpReadFds, &tmpWriteFds, nil, timeout)
98                         s.Lock()
99
100                         if e != syscall.EINTR {
101                                 break
102                         }
103                 }
104                 if e != 0 {
105                         return -1, 0, os.NewSyscallError("select", e)
106                 }
107                 if n == 0 {
108                         return -1, 0, nil
109                 }
110
111                 p.nReady = n
112                 *p.readyReadFds = tmpReadFds
113                 *p.readyWriteFds = tmpWriteFds
114                 p.lastFd = 0
115         }
116
117         flag := false
118         for i := p.lastFd; i < p.maxFd+1; i++ {
119                 if syscall.FDIsSet(i, p.readyReadFds) {
120                         flag = true
121                         mode = 'r'
122                         syscall.FDClr(i, p.readyReadFds)
123                 } else if syscall.FDIsSet(i, p.readyWriteFds) {
124                         flag = true
125                         mode = 'w'
126                         syscall.FDClr(i, p.readyWriteFds)
127                 }
128                 if flag {
129                         if !syscall.FDIsSet(i, p.repeatFds) {
130                                 p.DelFD(i, mode)
131                         }
132                         p.nReady--
133                         p.lastFd = i
134                         return i, mode, nil
135                 }
136         }
137
138         // Will not reach here.  Just to shut up the compiler.
139         return -1, 0, nil
140 }
141
142 func (p *pollster) Close() error {
143         return nil
144 }