2017-11-02 18:08:18 +03:00
|
|
|
// Copyright 2017 Joshua J Baker. All rights reserved.
|
|
|
|
// Use of this source code is governed by an MIT-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2017-10-28 22:23:13 +03:00
|
|
|
package internal
|
|
|
|
|
|
|
|
import (
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
2018-05-24 02:49:45 +03:00
|
|
|
// Poll ...
|
|
|
|
type Poll struct {
|
|
|
|
fd int // epoll fd
|
|
|
|
wfd int // wake fd
|
|
|
|
notes noteQueue
|
|
|
|
}
|
|
|
|
|
|
|
|
// OpenPoll ...
|
|
|
|
func OpenPoll() *Poll {
|
|
|
|
l := new(Poll)
|
|
|
|
p, err := syscall.EpollCreate1(0)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2017-11-09 02:45:30 +03:00
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
l.fd = p
|
2019-01-14 22:23:58 +03:00
|
|
|
r0, _, e0 := syscall.Syscall(syscall.SYS_EVENTFD2, 0, 0, 0)
|
2018-05-24 02:49:45 +03:00
|
|
|
if e0 != 0 {
|
|
|
|
syscall.Close(p)
|
|
|
|
panic(err)
|
2017-10-28 22:23:13 +03:00
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
l.wfd = int(r0)
|
|
|
|
l.AddRead(l.wfd)
|
|
|
|
return l
|
2017-10-28 22:23:13 +03:00
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
|
|
|
|
// Close ...
|
|
|
|
func (p *Poll) Close() error {
|
|
|
|
if err := syscall.Close(p.wfd); err != nil {
|
|
|
|
return err
|
2017-10-28 22:23:13 +03:00
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
return syscall.Close(p.fd)
|
2017-10-28 22:23:13 +03:00
|
|
|
}
|
2017-11-09 02:45:30 +03:00
|
|
|
|
2018-05-24 02:49:45 +03:00
|
|
|
// Trigger ...
|
|
|
|
func (p *Poll) Trigger(note interface{}) error {
|
|
|
|
p.notes.Add(note)
|
|
|
|
_, err := syscall.Write(p.wfd, []byte{0, 0, 0, 0, 0, 0, 0, 1})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait ...
|
|
|
|
func (p *Poll) Wait(iter func(fd int, note interface{}) error) error {
|
|
|
|
events := make([]syscall.EpollEvent, 64)
|
|
|
|
for {
|
|
|
|
n, err := syscall.EpollWait(p.fd, events, -1)
|
|
|
|
if err != nil && err != syscall.EINTR {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := p.notes.ForEach(func(note interface{}) error {
|
|
|
|
return iter(0, note)
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
if fd := int(events[i].Fd); fd != p.wfd {
|
|
|
|
if err := iter(fd, nil); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
}
|
2017-11-09 02:45:30 +03:00
|
|
|
}
|
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddReadWrite ...
|
|
|
|
func (p *Poll) AddReadWrite(fd int) {
|
|
|
|
if err := syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_ADD, fd,
|
2017-11-09 02:45:30 +03:00
|
|
|
&syscall.EpollEvent{Fd: int32(fd),
|
|
|
|
Events: syscall.EPOLLIN | syscall.EPOLLOUT,
|
2018-05-24 02:49:45 +03:00
|
|
|
},
|
|
|
|
); err != nil {
|
|
|
|
panic(err)
|
2017-11-09 02:45:30 +03:00
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddRead ...
|
|
|
|
func (p *Poll) AddRead(fd int) {
|
|
|
|
if err := syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_ADD, fd,
|
2017-10-28 22:23:13 +03:00
|
|
|
&syscall.EpollEvent{Fd: int32(fd),
|
|
|
|
Events: syscall.EPOLLIN,
|
2018-05-24 02:49:45 +03:00
|
|
|
},
|
|
|
|
); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2017-11-09 02:45:30 +03:00
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
|
|
|
|
// ModRead ...
|
|
|
|
func (p *Poll) ModRead(fd int) {
|
|
|
|
if err := syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_MOD, fd,
|
|
|
|
&syscall.EpollEvent{Fd: int32(fd),
|
|
|
|
Events: syscall.EPOLLIN,
|
|
|
|
},
|
|
|
|
); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2017-10-28 22:23:13 +03:00
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
|
|
|
|
// ModReadWrite ...
|
|
|
|
func (p *Poll) ModReadWrite(fd int) {
|
|
|
|
if err := syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_MOD, fd,
|
|
|
|
&syscall.EpollEvent{Fd: int32(fd),
|
|
|
|
Events: syscall.EPOLLIN | syscall.EPOLLOUT,
|
|
|
|
},
|
|
|
|
); err != nil {
|
|
|
|
panic(err)
|
2017-10-28 22:23:13 +03:00
|
|
|
}
|
|
|
|
}
|
2018-05-24 02:49:45 +03:00
|
|
|
|
|
|
|
// ModDetach ...
|
|
|
|
func (p *Poll) ModDetach(fd int) {
|
|
|
|
if err := syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_DEL, fd,
|
|
|
|
&syscall.EpollEvent{Fd: int32(fd),
|
|
|
|
Events: syscall.EPOLLIN | syscall.EPOLLOUT,
|
|
|
|
},
|
|
|
|
); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2017-10-28 22:23:13 +03:00
|
|
|
}
|