Class: Event::Selector::Select
- Inherits:
-
Object
- Object
- Event::Selector::Select
- Defined in:
- lib/event/selector/select.rb
Instance Method Summary collapse
- #close ⇒ Object
-
#initialize(loop) ⇒ Select
constructor
A new instance of Select.
- #io_read(fiber, io, buffer, length) ⇒ Object
- #io_wait(fiber, io, events) ⇒ Object
- #io_write(fiber, io, buffer, length) ⇒ Object
- #process_wait(fiber, pid, flags) ⇒ Object
- #push(fiber) ⇒ Object
- #raise(fiber, *arguments) ⇒ Object
- #ready? ⇒ Boolean
- #select(duration = nil) ⇒ Object
- #transfer(fiber, *arguments) ⇒ Object
- #yield ⇒ Object
Constructor Details
#initialize(loop) ⇒ Select
Returns a new instance of Select.
24 25 26 27 28 29 30 31 |
# File 'lib/event/selector/select.rb', line 24 def initialize(loop) @loop = loop @readable = {} @writable = {} @ready = [] end |
Instance Method Details
#close ⇒ Object
33 34 35 36 37 |
# File 'lib/event/selector/select.rb', line 33 def close @loop = nil @readable = nil @writable = nil end |
#io_read(fiber, io, buffer, length) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/event/selector/select.rb', line 89 def io_read(fiber, io, buffer, length) offset = 0 while length > 0 # The maximum size we can read: maximum_size = buffer.size - offset case result = io.read_nonblock(maximum_size, exception: false) when :wait_readable self.io_wait(fiber, io, READABLE) when :wait_writable self.io_wait(fiber, io, WRITABLE) else break if result.empty? buffer.copy(result, offset) offset += result.bytesize length -= result.bytesize end end return offset end |
#io_wait(fiber, io, events) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/event/selector/select.rb', line 69 def io_wait(fiber, io, events) remove_readable = remove_writable = false if (events & READABLE) > 0 or (events & PRIORITY) > 0 @readable[io] = fiber remove_readable = true end if (events & WRITABLE) > 0 @writable[io] = fiber remove_writable = true end @loop.transfer ensure @readable.delete(io) if remove_readable @writable.delete(io) if remove_writable end |
#io_write(fiber, io, buffer, length) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/event/selector/select.rb', line 114 def io_write(fiber, io, buffer, length) offset = 0 while length > 0 # From offset until the end: chunk = buffer.to_str(offset, length) case result = io.write_nonblock(chunk, exception: false) when :wait_readable self.io_wait(fiber, io, READABLE) when :wait_writable self.io_wait(fiber, io, WRITABLE) else offset += result length -= result end end return offset end |
#process_wait(fiber, pid, flags) ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/event/selector/select.rb', line 135 def process_wait(fiber, pid, flags) r, w = IO.pipe thread = Thread.new do Process::Status.wait(pid, flags) ensure w.close end self.io_wait(fiber, r, READABLE) return thread.value ensure r.close w.close thread&.kill end |
#push(fiber) ⇒ Object
54 55 56 |
# File 'lib/event/selector/select.rb', line 54 def push(fiber) @ready.push(fiber) end |
#raise(fiber, *arguments) ⇒ Object
58 59 60 61 62 63 |
# File 'lib/event/selector/select.rb', line 58 def raise(fiber, *arguments) @ready.push(Fiber.current) fiber.raise(*arguments) ensure @ready.delete(fiber) end |
#ready? ⇒ Boolean
65 66 67 |
# File 'lib/event/selector/select.rb', line 65 def ready? @ready.any? end |
#select(duration = nil) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/event/selector/select.rb', line 153 def select(duration = nil) if @ready.any? ready = @ready @ready = Array.new ready.each do |fiber| fiber.transfer if fiber.alive? end end readable, writable, _ = ::IO.select(@readable.keys, @writable.keys, nil, duration) ready = Hash.new(0) readable&.each do |io| fiber = @readable.delete(io) ready[fiber] |= READABLE end writable&.each do |io| fiber = @writable.delete(io) ready[fiber] |= WRITABLE end ready.each do |fiber, events| fiber.transfer(events) if fiber.alive? end end |
#transfer(fiber, *arguments) ⇒ Object
39 40 41 42 43 44 |
# File 'lib/event/selector/select.rb', line 39 def transfer(fiber, *arguments) @ready.push(Fiber.current) fiber.transfer(*arguments) ensure @ready.delete(fiber) end |
#yield ⇒ Object
46 47 48 49 50 51 52 |
# File 'lib/event/selector/select.rb', line 46 def yield fiber = Fiber.current @ready.push(fiber) @loop.transfer ensure @ready.delete(fiber) end |