/
epoll.go
110 lines (98 loc) · 2.22 KB
/
epoll.go
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//+build linux
package liblpc
import (
"golang.org/x/sys/unix"
"sync"
)
type Epoll struct {
efd int
wm *sync.Map
evtbuf []unix.EpollEvent
}
func NewEpoll(pollSize int) (Poller, error) {
epoFd, err := unix.EpollCreate1(unix.EPOLL_CLOEXEC)
if err != nil {
_ = unix.Close(epoFd)
return nil, err
}
p := new(Epoll)
p.efd = epoFd
p.wm = new(sync.Map)
p.evtbuf = make([]unix.EpollEvent, pollSize)
return p, nil
}
func (this *Epoll) rmFd(fd int) {
this.wm.Delete(fd)
}
func (this *Epoll) setFd(fd int, watcher EventWatcher) {
this.wm.Store(fd, watcher)
}
func (this *Epoll) getWatcher(fd int) EventWatcher {
value, ok := this.wm.Load(fd)
if !ok {
return nil
}
return value.(EventWatcher)
}
func (this *Epoll) Close() error {
this.wm.Range(func(key, value interface{}) bool {
_ = value.(EventWatcher).Close()
return true
})
return unix.Close(this.efd)
}
func (this *Epoll) WatcherCtl(action PollerAction, watcher EventWatcher) error {
switch action {
case Add:
return this.AddFd(watcher.GetFd(), watcher.GetEvent(), watcher)
case Mod:
return this.ModFd(watcher.GetFd(), watcher.GetEvent())
case Del:
return this.DelFd(watcher.GetFd())
}
return nil
}
func (this *Epoll) Poll(msec int) error {
nevents, err := unix.EpollWait(this.efd, this.evtbuf, msec)
if err != nil && err != unix.EINTR {
return err
}
for idx := 0; idx < nevents; idx++ {
epEvent := this.evtbuf[idx]
fd := int(epEvent.Fd)
watcher := this.getWatcher(fd)
if watcher == nil {
stdLog("unknown fd = ", fd, ", watcher not found")
continue
}
watcher.OnEvent(epEvent.Events)
}
return nil
}
func (this *Epoll) AddFd(fd int, event uint32, watcher EventWatcher) error {
epEvent := &unix.EpollEvent{
Events: event,
Fd: int32(fd),
}
err := unix.EpollCtl(this.efd, unix.EPOLL_CTL_ADD, fd, epEvent)
if err != nil {
return err
}
this.setFd(fd, watcher)
return nil
}
func (this *Epoll) ModFd(fd int, event uint32) error {
epEvent := &unix.EpollEvent{
Events: event,
Fd: int32(fd),
}
err := unix.EpollCtl(this.efd, unix.EPOLL_CTL_MOD, fd, epEvent)
return err
}
func (this *Epoll) DelFd(fd int) error {
err := unix.EpollCtl(this.efd, unix.EPOLL_CTL_DEL, fd, nil)
if err == nil {
this.rmFd(fd)
}
return err
}