-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathselect.go
More file actions
56 lines (51 loc) · 1.17 KB
/
select.go
File metadata and controls
56 lines (51 loc) · 1.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package asio
import (
"fmt"
"syscall"
"time"
)
func FD_SET(fd uintptr, p *syscall.FdSet) {
n, k := fd/32, fd%32
p.Bits[n] |= (1 << uint32(k))
}
func CheckoutTimeout(fd socket_t, deadline time.Time) (error) {
var err error
var to syscall.Timeval
var toptr *syscall.Timeval
var pw syscall.FdSet
FD_SET(uintptr(fd), &pw)
for {
// wait until the fd is ready to read or write.
if !deadline.IsZero() {
to = syscall.NsecToTimeval(deadline.Sub(time.Now()).Nanoseconds())
toptr = &to
}
// wait until the fd is ready to write. we can't use:
// if err := fd.pd.WaitWrite(); err != nil {
// return err
// }
// so we use select instead.
if _, err = Select(fd+1, nil, &pw, nil, toptr); err != nil {
fmt.Println(err)
return err
}
var nerr int
nerr, err = syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR)
if err != nil {
return err
}
switch err = syscall.Errno(nerr); err {
case syscall.ETIMEDOUT:
return errTimeout
case syscall.EAGAIN:
continue
case syscall.Errno(0), syscall.EISCONN:
if !deadline.IsZero() && deadline.Before(time.Now()) {
return errTimeout
}
return nil
default:
return err
}
}
}