github.com/dshulyak/uring@v0.0.0-20210209113719-1b2ec51f1542/loop/poll.go (about)

     1  package loop
     2  
     3  import (
     4  	"syscall"
     5  	"unsafe"
     6  )
     7  
     8  func newPoll(n int) (*poll, error) {
     9  	p, err := syscall.EpollCreate1(0)
    10  	if err != nil {
    11  		return nil, err
    12  	}
    13  	return &poll{fd: p, events: make([]syscall.EpollEvent, n)}, nil
    14  }
    15  
    16  type poll struct {
    17  	fd int // epoll fd
    18  
    19  	buf    [8]byte
    20  	events []syscall.EpollEvent
    21  }
    22  
    23  func (p *poll) addRead(fd int32) error {
    24  	return syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_ADD, int(fd),
    25  		&syscall.EpollEvent{
    26  			Fd:     fd,
    27  			Events: syscall.EPOLLIN,
    28  		},
    29  	)
    30  }
    31  
    32  func (p *poll) wait(iter func(int32)) error {
    33  	for {
    34  		n, err := syscall.EpollWait(p.fd, p.events, -1)
    35  		if err == syscall.EINTR {
    36  			continue
    37  		}
    38  		for i := 0; i < n; i++ {
    39  			_, err := syscall.Read(int(p.events[i].Fd), p.buf[:])
    40  			if err != nil {
    41  				panic(err)
    42  			}
    43  			// uint64 in the machine native order
    44  			cnt := *(*uint64)(unsafe.Pointer(&p.buf))
    45  			for j := uint64(0); j < cnt; j++ {
    46  				iter(p.events[i].Fd)
    47  			}
    48  		}
    49  		return err
    50  	}
    51  }
    52  
    53  func (p *poll) close() error {
    54  	return syscall.Close(p.fd)
    55  }