github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/poller/netpoll/netpoll_kqueue.go (about) 1 // +build darwin dragonfly freebsd netbsd openbsd 2 3 package netpoll 4 5 import ( 6 "os" 7 ) 8 9 // New creates new kqueue-based Poller instance with given config. 10 func New(c *Config) (Poller, error) { 11 cfg := c.withDefaults() 12 13 kq, err := KqueueCreate(&KqueueConfig{ 14 OnWaitError: cfg.OnWaitError, 15 }) 16 if err != nil { 17 return nil, err 18 } 19 20 return poller{kq}, nil 21 } 22 23 type poller struct { 24 *Kqueue 25 } 26 27 func (p poller) Start(desc *Desc, cb CallbackFn) error { 28 n, events := toKevents(desc.event, true) 29 err := p.Add(desc.fd(), events, n, func(kev Kevent) { 30 var ( 31 event Event 32 33 flags = kev.Flags 34 filter = kev.Filter 35 ) 36 37 // Set EventHup for any EOF flag. Below will be more precise detection 38 // of what exatcly HUP occured. 39 if flags&EV_EOF != 0 { 40 event |= EventHup 41 } 42 43 if filter == EVFILT_READ { 44 event |= EventRead 45 if flags&EV_EOF != 0 { 46 event |= EventReadHup 47 } 48 } 49 if filter == EVFILT_WRITE { 50 event |= EventWrite 51 if flags&EV_EOF != 0 { 52 event |= EventWriteHup 53 } 54 } 55 if flags&EV_ERROR != 0 { 56 event |= EventErr 57 } 58 if filter == _EVFILT_CLOSED { 59 event |= EventPollerClosed 60 } 61 62 cb(event) 63 }) 64 if err == nil { 65 if err = setNonblock(desc.fd(), true); err != nil { 66 return os.NewSyscallError("setnonblock", err) 67 } 68 } 69 return err 70 } 71 72 func (p poller) Stop(desc *Desc) error { 73 n, events := toKevents(desc.event, false) 74 if err := p.Del(desc.fd()); err != nil { 75 return err 76 } 77 if err := p.Mod(desc.fd(), events, n); err != nil && err != ErrNotRegistered { 78 return err 79 } 80 return nil 81 } 82 83 func (p poller) Resume(desc *Desc) error { 84 n, events := toKevents(desc.event, true) 85 return p.Mod(desc.fd(), events, n) 86 } 87 88 func toKevents(event Event, add bool) (n int, ks Kevents) { 89 var flags KeventFlag 90 if add { 91 flags = EV_ADD 92 if event&EventOneShot != 0 { 93 flags |= EV_ONESHOT 94 } 95 if event&EventEdgeTriggered != 0 { 96 flags |= EV_CLEAR 97 } 98 } else { 99 flags = EV_DELETE 100 } 101 if event&EventRead != 0 { 102 ks[n].Flags = flags 103 ks[n].Filter = EVFILT_READ 104 n++ 105 } 106 if event&EventWrite != 0 { 107 ks[n].Flags = flags 108 ks[n].Filter = EVFILT_WRITE 109 n++ 110 } 111 return 112 }