github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/poller/netpoll/netpoll.go (about) 1 /* 2 Package netpoll provides a portable interface for network I/O event 3 notification facility. 4 5 Its API is intended for monitoring multiple file descriptors to see if I/O is 6 possible on any of them. It supports edge-triggered and level-triggered 7 interfaces. 8 9 To get more info you could look at operating system API documentation of 10 particular netpoll implementations: 11 - epoll on linux; 12 - kqueue on bsd; 13 14 The Handle function creates netpoll.Desc for further use in Poller's methods: 15 16 desc, err := netpoll.Handle(conn, netpoll.EventRead | netpoll.EventEdgeTriggered) 17 if err != nil { 18 // handle error 19 } 20 21 The Poller describes os-dependent network poller: 22 23 poller, err := netpoll.New(nil) 24 if err != nil { 25 // handle error 26 } 27 28 // Get netpoll descriptor with EventRead|EventEdgeTriggered. 29 desc := netpoll.Must(netpoll.HandleRead(conn)) 30 31 poller.Start(desc, func(ev netpoll.Event) { 32 if ev&netpoll.EventReadHup != 0 { 33 poller.Stop(desc) 34 conn.Close() 35 return 36 } 37 38 _, err := ioutil.ReadAll(conn) 39 if err != nil { 40 // handle error 41 } 42 }) 43 44 Currently, Poller is implemented only for Linux. 45 */ 46 package netpoll 47 48 import ( 49 "fmt" 50 "log" 51 ) 52 53 var ( 54 // ErrNotFiler is returned by Handle* functions to indicate that given 55 // net.Conn does not provide access to its file descriptor. 56 ErrNotFiler = fmt.Errorf("could not get file descriptor") 57 58 // ErrClosed is returned by Poller methods to indicate that instance is 59 // closed and operation could not be processed. 60 ErrClosed = fmt.Errorf("poller instance is closed") 61 62 // ErrRegistered is returned by Poller Start() method to indicate that 63 // connection with the same underlying file descriptor was already 64 // registered within the poller instance. 65 ErrRegistered = fmt.Errorf("file descriptor is already registered in poller instance") 66 67 // ErrNotRegistered is returned by Poller Stop() and Resume() methods to 68 // indicate that connection with the same underlying file descriptor was 69 // not registered before within the poller instance. 70 ErrNotRegistered = fmt.Errorf("file descriptor was not registered before in poller instance") 71 ) 72 73 // Event represents netpoll configuration bit mask. 74 type Event uint16 75 76 // Event values that denote the type of events that caller want to receive. 77 const ( 78 EventRead Event = 0x1 79 EventWrite = 0x2 80 ) 81 82 // Event values that configure the Poller's behavior. 83 const ( 84 EventOneShot Event = 0x4 85 EventEdgeTriggered = 0x8 86 ) 87 88 // Event values that could be passed to CallbackFn as additional information 89 // event. 90 const ( 91 // EventHup is indicates that some side of i/o operations (receive, send or 92 // both) is closed. 93 // Usually (depending on operating system and its version) the EventReadHup 94 // or EventWriteHup are also set int Event value. 95 EventHup Event = 0x10 96 97 EventReadHup = 0x20 98 EventWriteHup = 0x40 99 100 EventErr = 0x80 101 102 // EventPollerClosed is a special Event value the receipt of which means that the 103 // Poller instance is closed. 104 EventPollerClosed = 0x8000 105 ) 106 107 // String returns a string representation of Event. 108 func (ev Event) String() (str string) { 109 name := func(event Event, name string) { 110 if ev&event == 0 { 111 return 112 } 113 if str != "" { 114 str += "|" 115 } 116 str += name 117 } 118 119 name(EventRead, "EventRead") 120 name(EventWrite, "EventWrite") 121 name(EventOneShot, "EventOneShot") 122 name(EventEdgeTriggered, "EventEdgeTriggered") 123 name(EventReadHup, "EventReadHup") 124 name(EventWriteHup, "EventWriteHup") 125 name(EventHup, "EventHup") 126 name(EventErr, "EventErr") 127 name(EventPollerClosed, "EventPollerClosed") 128 129 return 130 } 131 132 // Poller describes an object that implements event of polling connections for 133 // i/o events such as availability of read() or write() operations. 134 type Poller interface { 135 // Start adds desc to the observation list. 136 // 137 // Note that if desc was configured with OneShot event, then poller will 138 // remove it from its observation list. If you will be interested in 139 // receiving events after the callback, call Resume(desc). 140 // 141 // Note that Resume() call directly inside desc's callback could cause 142 // deadlock. 143 // 144 // Note that multiple calls with same desc will produce unexpected 145 // behavior. 146 Start(*Desc, CallbackFn) error 147 148 // Stop removes desc from the observation list. 149 // 150 // Note that it does not call desc.Close(). 151 Stop(*Desc) error 152 153 // Resume enables observation of desc. 154 // 155 // It is useful when desc was configured with EventOneShot. 156 // It should be called only after Start(). 157 // 158 // Note that if there no need to observe desc anymore, you should call 159 // Stop() to prevent memory leaks. 160 Resume(*Desc) error 161 } 162 163 // CallbackFn is a function that will be called on kernel i/o event 164 // notification. 165 type CallbackFn func(Event) 166 167 // Config contains options for Poller configuration. 168 type Config struct { 169 // OnWaitError will be called from goroutine, waiting for events. 170 OnWaitError func(error) 171 } 172 173 func (c *Config) withDefaults() (config Config) { 174 if c != nil { 175 config = *c 176 } 177 if config.OnWaitError == nil { 178 config.OnWaitError = defaultOnWaitError 179 } 180 return config 181 } 182 183 func defaultOnWaitError(err error) { 184 log.Printf("netpoll: wait loop error: %s", err) 185 }