github.com/polevpn/netstack@v1.10.9/waiter/waiter.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package waiter provides the implementation of a wait queue, where waiters can 16 // be enqueued to be notified when an event of interest happens. 17 // 18 // Becoming readable and/or writable are examples of events. Waiters are 19 // expected to use a pattern similar to this to make a blocking function out of 20 // a non-blocking one: 21 // 22 // func (o *object) blockingRead(...) error { 23 // err := o.nonBlockingRead(...) 24 // if err != ErrAgain { 25 // // Completed with no need to wait! 26 // return err 27 // } 28 // 29 // e := createOrGetWaiterEntry(...) 30 // o.EventRegister(&e, waiter.EventIn) 31 // defer o.EventUnregister(&e) 32 // 33 // // We need to try to read again after registration because the 34 // // object may have become readable between the last attempt to 35 // // read and read registration. 36 // err = o.nonBlockingRead(...) 37 // for err == ErrAgain { 38 // wait() 39 // err = o.nonBlockingRead(...) 40 // } 41 // 42 // return err 43 // } 44 // 45 // Another goroutine needs to notify waiters when events happen. For example: 46 // 47 // func (o *object) Write(...) ... { 48 // // Do write work. 49 // [...] 50 // 51 // if oldDataAvailableSize == 0 && dataAvailableSize > 0 { 52 // // If no data was available and now some data is 53 // // available, the object became readable, so notify 54 // // potential waiters about this. 55 // o.Notify(waiter.EventIn) 56 // } 57 // } 58 package waiter 59 60 import ( 61 "sync" 62 ) 63 64 // EventMask represents io events as used in the poll() syscall. 65 type EventMask uint16 66 67 // Events that waiters can wait on. The meaning is the same as those in the 68 // poll() syscall. 69 const ( 70 EventIn EventMask = 0x01 // POLLIN 71 EventPri EventMask = 0x02 // POLLPRI 72 EventOut EventMask = 0x04 // POLLOUT 73 EventErr EventMask = 0x08 // POLLERR 74 EventHUp EventMask = 0x10 // POLLHUP 75 76 allEvents EventMask = 0x1f 77 ) 78 79 // EventMaskFromLinux returns an EventMask representing the supported events 80 // from the Linux events e, which is in the format used by poll(2). 81 func EventMaskFromLinux(e uint32) EventMask { 82 // Our flag definitions are currently identical to Linux. 83 return EventMask(e) & allEvents 84 } 85 86 // ToLinux returns e in the format used by Linux poll(2). 87 func (e EventMask) ToLinux() uint32 { 88 // Our flag definitions are currently identical to Linux. 89 return uint32(e) 90 } 91 92 // Waitable contains the methods that need to be implemented by waitable 93 // objects. 94 type Waitable interface { 95 // Readiness returns what the object is currently ready for. If it's 96 // not ready for a desired purpose, the caller may use EventRegister and 97 // EventUnregister to get notifications once the object becomes ready. 98 // 99 // Implementations should allow for events like EventHUp and EventErr 100 // to be returned regardless of whether they are in the input EventMask. 101 Readiness(mask EventMask) EventMask 102 103 // EventRegister registers the given waiter entry to receive 104 // notifications when an event occurs that makes the object ready for 105 // at least one of the events in mask. 106 EventRegister(e *Entry, mask EventMask) 107 108 // EventUnregister unregisters a waiter entry previously registered with 109 // EventRegister(). 110 EventUnregister(e *Entry) 111 } 112 113 // EntryCallback provides a notify callback. 114 type EntryCallback interface { 115 // Callback is the function to be called when the waiter entry is 116 // notified. It is responsible for doing whatever is needed to wake up 117 // the waiter. 118 // 119 // The callback is supposed to perform minimal work, and cannot call 120 // any method on the queue itself because it will be locked while the 121 // callback is running. 122 Callback(e *Entry) 123 } 124 125 // Entry represents a waiter that can be add to the a wait queue. It can 126 // only be in one queue at a time, and is added "intrusively" to the queue with 127 // no extra memory allocations. 128 // 129 // +stateify savable 130 type Entry struct { 131 // Context stores any state the waiter may wish to store in the entry 132 // itself, which may be used at wake up time. 133 // 134 // Note that use of this field is optional and state may alternatively be 135 // stored in the callback itself. 136 Context interface{} 137 138 Callback EntryCallback 139 140 // The following fields are protected by the queue lock. 141 mask EventMask 142 waiterEntry 143 } 144 145 type channelCallback struct{} 146 147 // Callback implements EntryCallback.Callback. 148 func (*channelCallback) Callback(e *Entry) { 149 ch := e.Context.(chan struct{}) 150 select { 151 case ch <- struct{}{}: 152 default: 153 } 154 } 155 156 // NewChannelEntry initializes a new Entry that does a non-blocking write to a 157 // struct{} channel when the callback is called. It returns the new Entry 158 // instance and the channel being used. 159 // 160 // If a channel isn't specified (i.e., if "c" is nil), then NewChannelEntry 161 // allocates a new channel. 162 func NewChannelEntry(c chan struct{}) (Entry, chan struct{}) { 163 if c == nil { 164 c = make(chan struct{}, 1) 165 } 166 167 return Entry{Context: c, Callback: &channelCallback{}}, c 168 } 169 170 // Queue represents the wait queue where waiters can be added and 171 // notifiers can notify them when events happen. 172 // 173 // The zero value for waiter.Queue is an empty queue ready for use. 174 // 175 // +stateify savable 176 type Queue struct { 177 list waiterList 178 mu sync.RWMutex 179 } 180 181 // EventRegister adds a waiter to the wait queue; the waiter will be notified 182 // when at least one of the events specified in mask happens. 183 func (q *Queue) EventRegister(e *Entry, mask EventMask) { 184 q.mu.Lock() 185 e.mask = mask 186 q.list.PushBack(e) 187 q.mu.Unlock() 188 } 189 190 // EventUnregister removes the given waiter entry from the wait queue. 191 func (q *Queue) EventUnregister(e *Entry) { 192 q.mu.Lock() 193 q.list.Remove(e) 194 q.mu.Unlock() 195 } 196 197 // Notify notifies all waiters in the queue whose masks have at least one bit 198 // in common with the notification mask. 199 func (q *Queue) Notify(mask EventMask) { 200 q.mu.RLock() 201 for e := q.list.Front(); e != nil; e = e.Next() { 202 if mask&e.mask != 0 { 203 e.Callback.Callback(e) 204 } 205 } 206 q.mu.RUnlock() 207 } 208 209 // Events returns the set of events being waited on. It is the union of the 210 // masks of all registered entries. 211 func (q *Queue) Events() EventMask { 212 ret := EventMask(0) 213 214 q.mu.RLock() 215 for e := q.list.Front(); e != nil; e = e.Next() { 216 ret |= e.mask 217 } 218 q.mu.RUnlock() 219 220 return ret 221 } 222 223 // IsEmpty returns if the wait queue is empty or not. 224 func (q *Queue) IsEmpty() bool { 225 q.mu.Lock() 226 defer q.mu.Unlock() 227 228 return q.list.Front() == nil 229 } 230 231 // AlwaysReady implements the Waitable interface but is always ready. Embedding 232 // this struct into another struct makes it implement the boilerplate empty 233 // functions automatically. 234 type AlwaysReady struct { 235 } 236 237 // Readiness always returns the input mask because this object is always ready. 238 func (*AlwaysReady) Readiness(mask EventMask) EventMask { 239 return mask 240 } 241 242 // EventRegister doesn't do anything because this object doesn't need to issue 243 // notifications because its readiness never changes. 244 func (*AlwaysReady) EventRegister(*Entry, EventMask) { 245 } 246 247 // EventUnregister doesn't do anything because this object doesn't need to issue 248 // notifications because its readiness never changes. 249 func (*AlwaysReady) EventUnregister(e *Entry) { 250 }