1
2
3
4
5 package poll
6
7 import (
8 "errors"
9 "internal/stringslite"
10 "io"
11 "sync"
12 "syscall"
13 "time"
14 )
15
16 type FD struct {
17
18 fdmu fdMutex
19
20 Destroy func()
21
22
23 rmu sync.Mutex
24 wmu sync.Mutex
25 raio *asyncIO
26 waio *asyncIO
27 rtimer *time.Timer
28 wtimer *time.Timer
29 rtimedout bool
30 wtimedout bool
31
32
33
34
35
36 isFile bool
37 }
38
39
40
41
42 func (fd *FD) destroy() error {
43 if fd.Destroy != nil {
44 fd.Destroy()
45 }
46 return nil
47 }
48
49
50
51 func (fd *FD) Close() error {
52 if !fd.fdmu.increfAndClose() {
53 return errClosing(fd.isFile)
54 }
55 return nil
56 }
57
58
59 func (fd *FD) Read(fn func([]byte) (int, error), b []byte) (int, error) {
60 if err := fd.readLock(); err != nil {
61 return 0, err
62 }
63 defer fd.readUnlock()
64 if len(b) == 0 {
65 return 0, nil
66 }
67 fd.rmu.Lock()
68 if fd.rtimedout {
69 fd.rmu.Unlock()
70 return 0, ErrDeadlineExceeded
71 }
72 fd.raio = newAsyncIO(fn, b)
73 fd.rmu.Unlock()
74 n, err := fd.raio.Wait()
75 fd.raio = nil
76 if isHangup(err) {
77 err = io.EOF
78 }
79 if isInterrupted(err) {
80 err = ErrDeadlineExceeded
81 }
82 return n, err
83 }
84
85
86 func (fd *FD) Write(fn func([]byte) (int, error), b []byte) (int, error) {
87 if err := fd.writeLock(); err != nil {
88 return 0, err
89 }
90 defer fd.writeUnlock()
91 fd.wmu.Lock()
92 if fd.wtimedout {
93 fd.wmu.Unlock()
94 return 0, ErrDeadlineExceeded
95 }
96 fd.waio = newAsyncIO(fn, b)
97 fd.wmu.Unlock()
98 n, err := fd.waio.Wait()
99 fd.waio = nil
100 if isInterrupted(err) {
101 err = ErrDeadlineExceeded
102 }
103 return n, err
104 }
105
106
107 func (fd *FD) SetDeadline(t time.Time) error {
108 return setDeadlineImpl(fd, t, 'r'+'w')
109 }
110
111
112 func (fd *FD) SetReadDeadline(t time.Time) error {
113 return setDeadlineImpl(fd, t, 'r')
114 }
115
116
117 func (fd *FD) SetWriteDeadline(t time.Time) error {
118 return setDeadlineImpl(fd, t, 'w')
119 }
120
121 func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
122 d := t.Sub(time.Now())
123 if mode == 'r' || mode == 'r'+'w' {
124 fd.rmu.Lock()
125 defer fd.rmu.Unlock()
126 if fd.rtimer != nil {
127 fd.rtimer.Stop()
128 fd.rtimer = nil
129 }
130 fd.rtimedout = false
131 }
132 if mode == 'w' || mode == 'r'+'w' {
133 fd.wmu.Lock()
134 defer fd.wmu.Unlock()
135 if fd.wtimer != nil {
136 fd.wtimer.Stop()
137 fd.wtimer = nil
138 }
139 fd.wtimedout = false
140 }
141 if !t.IsZero() && d > 0 {
142
143 if mode == 'r' || mode == 'r'+'w' {
144 var timer *time.Timer
145 timer = time.AfterFunc(d, func() {
146 fd.rmu.Lock()
147 defer fd.rmu.Unlock()
148 if fd.rtimer != timer {
149
150 return
151 }
152 fd.rtimedout = true
153 if fd.raio != nil {
154 fd.raio.Cancel()
155 }
156 })
157 fd.rtimer = timer
158 }
159 if mode == 'w' || mode == 'r'+'w' {
160 var timer *time.Timer
161 timer = time.AfterFunc(d, func() {
162 fd.wmu.Lock()
163 defer fd.wmu.Unlock()
164 if fd.wtimer != timer {
165
166 return
167 }
168 fd.wtimedout = true
169 if fd.waio != nil {
170 fd.waio.Cancel()
171 }
172 })
173 fd.wtimer = timer
174 }
175 }
176 if !t.IsZero() && d <= 0 {
177
178 if mode == 'r' || mode == 'r'+'w' {
179 fd.rtimedout = true
180 if fd.raio != nil {
181 fd.raio.Cancel()
182 }
183 }
184 if mode == 'w' || mode == 'r'+'w' {
185 fd.wtimedout = true
186 if fd.waio != nil {
187 fd.waio.Cancel()
188 }
189 }
190 }
191 return nil
192 }
193
194
195
196
197 func (fd *FD) ReadLock() error {
198 return fd.readLock()
199 }
200
201
202 func (fd *FD) ReadUnlock() {
203 fd.readUnlock()
204 }
205
206 func isHangup(err error) bool {
207 return err != nil && stringslite.HasSuffix(err.Error(), "Hangup")
208 }
209
210 func isInterrupted(err error) bool {
211 return err != nil && stringslite.HasSuffix(err.Error(), "interrupted")
212 }
213
214
215
216 func IsPollDescriptor(fd uintptr) bool {
217 return false
218 }
219
220
221
222 func (fd *FD) RawControl(f func(uintptr)) error {
223 return errors.New("not implemented")
224 }
225
226
227 func (fd *FD) RawRead(f func(uintptr) bool) error {
228 return errors.New("not implemented")
229 }
230
231
232 func (fd *FD) RawWrite(f func(uintptr) bool) error {
233 return errors.New("not implemented")
234 }
235
236 func DupCloseOnExec(fd int) (int, string, error) {
237 nfd, err := syscall.Dup(int(fd), -1)
238 if err != nil {
239 return 0, "dup", err
240 }
241
242
243
244 return nfd, "", nil
245 }
246
View as plain text