github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/internal/netpoll/kqueue.go (about) 1 // +build darwin netbsd freebsd openbsd dragonfly 2 3 package netpoll 4 5 import ( 6 "log" 7 8 "github.com/angenalZZZ/gofunc/net/internal" 9 "golang.org/x/sys/unix" 10 ) 11 12 // Poller represents a poller which is in charge of monitoring file-descriptors. 13 type Poller struct { 14 fd int 15 asyncJobQueue internal.AsyncJobQueue 16 } 17 18 // OpenPoller instantiates a poller. 19 func OpenPoller() (poller *Poller, err error) { 20 poller = new(Poller) 21 if poller.fd, err = unix.Kqueue(); err != nil { 22 poller = nil 23 return 24 } 25 if _, err = unix.Kevent(poller.fd, []unix.Kevent_t{{ 26 Ident: 0, 27 Filter: unix.EVFILT_USER, 28 Flags: unix.EV_ADD | unix.EV_CLEAR, 29 }}, nil, nil); err != nil { 30 _ = poller.Close() 31 poller = nil 32 return 33 } 34 poller.asyncJobQueue = internal.NewAsyncJobQueue() 35 return 36 } 37 38 // Close closes the poller. 39 func (p *Poller) Close() error { 40 return unix.Close(p.fd) 41 } 42 43 var wakeChanges = []unix.Kevent_t{{ 44 Ident: 0, 45 Filter: unix.EVFILT_USER, 46 Fflags: unix.NOTE_TRIGGER, 47 }} 48 49 // Trigger wakes up the poller blocked in waiting for network-events and runs jobs in asyncJobQueue. 50 func (p *Poller) Trigger(job internal.Job) error { 51 if p.asyncJobQueue.Push(job) == 1 { 52 _, err := unix.Kevent(p.fd, wakeChanges, nil, nil) 53 return err 54 } 55 return nil 56 } 57 58 // Polling blocks the current goroutine, waiting for network-events. 59 func (p *Poller) Polling(callback func(fd int, filter int16) error) (err error) { 60 el := newEventList(InitEvents) 61 var wakenUp bool 62 for { 63 n, err0 := unix.Kevent(p.fd, nil, el.events, nil) 64 if err0 != nil && err0 != unix.EINTR { 65 log.Println(err0) 66 continue 67 } 68 var evFilter int16 69 for i := 0; i < n; i++ { 70 if fd := int(el.events[i].Ident); fd != 0 { 71 evFilter = el.events[i].Filter 72 if (el.events[i].Flags&unix.EV_EOF != 0) || (el.events[i].Flags&unix.EV_ERROR != 0) { 73 evFilter = EVFilterSock 74 } 75 if err = callback(fd, evFilter); err != nil { 76 return 77 } 78 } else { 79 wakenUp = true 80 } 81 } 82 if wakenUp { 83 wakenUp = false 84 if err = p.asyncJobQueue.ForEach(); err != nil { 85 return 86 } 87 } 88 if n == el.size { 89 el.increase() 90 } 91 } 92 } 93 94 // AddReadWrite registers the given file-descriptor with readable and writable events to the poller. 95 func (p *Poller) AddReadWrite(fd int) error { 96 if _, err := unix.Kevent(p.fd, []unix.Kevent_t{ 97 {Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_READ}, 98 {Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_WRITE}, 99 }, nil, nil); err != nil { 100 return err 101 } 102 return nil 103 } 104 105 // AddRead registers the given file-descriptor with readable event to the poller. 106 func (p *Poller) AddRead(fd int) error { 107 if _, err := unix.Kevent(p.fd, []unix.Kevent_t{ 108 {Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_READ}}, nil, nil); err != nil { 109 return err 110 } 111 return nil 112 } 113 114 // AddWrite registers the given file-descriptor with writable event to the poller. 115 func (p *Poller) AddWrite(fd int) error { 116 if _, err := unix.Kevent(p.fd, []unix.Kevent_t{ 117 {Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_WRITE}}, nil, nil); err != nil { 118 return err 119 } 120 return nil 121 } 122 123 // ModRead renews the given file-descriptor with readable event in the poller. 124 func (p *Poller) ModRead(fd int) error { 125 if _, err := unix.Kevent(p.fd, []unix.Kevent_t{ 126 {Ident: uint64(fd), Flags: unix.EV_DELETE, Filter: unix.EVFILT_WRITE}}, nil, nil); err != nil { 127 return err 128 } 129 return nil 130 } 131 132 // ModReadWrite renews the given file-descriptor with readable and writable events in the poller. 133 func (p *Poller) ModReadWrite(fd int) error { 134 if _, err := unix.Kevent(p.fd, []unix.Kevent_t{ 135 {Ident: uint64(fd), Flags: unix.EV_ADD, Filter: unix.EVFILT_WRITE}}, nil, nil); err != nil { 136 return err 137 } 138 return nil 139 } 140 141 // Delete removes the given file-descriptor from the poller. 142 func (p *Poller) Delete(fd int) error { 143 return nil 144 }