Implements the selector loop, where it registers and monitors “Selectable” objects.
A Selectable object is an object which can calculate the interests (:r, :w or :rw, respectively “read”, “write” or “read-write”) it wants to monitor for, and returns (via to_io method) an IO object which can be passed to functions such as IO.select . More exhaustively, a Selectable must implement the following methods:
| state |
returns the state as a Symbol, must return |
| to_io |
returns the IO object. |
| call |
gets called when the IO is ready. |
| interests |
returns the current interests to monitor for, as described above. |
| timeout |
returns nil or an integer, representing how long to wait for interests. |
| handle_socket_timeout(Numeric) |
called when waiting for interest times out. |
Methods
Public Class
Public Instance
Public Class methods
# File lib/httpx/selector.rb 34 def initialize 35 @timers = Timers.new 36 @selectables = [] 37 @is_timer_interval = false 38 end
Public Instance methods
deregisters io from selectables.
# File lib/httpx/selector.rb 122 def deregister(io) 123 @selectables.delete(io) 124 end
# File lib/httpx/selector.rb 96 def each_connection(&block) 97 return enum_for(__method__) unless block 98 99 @selectables.each do |c| 100 case c 101 when Resolver::Resolver 102 c.each_connection(&block) 103 when Connection 104 yield c 105 end 106 end 107 end
# File lib/httpx/selector.rb 40 def empty? 41 @selectables.empty? && @timers.empty? 42 end
# File lib/httpx/selector.rb 109 def find_connection(request_uri, options) 110 each_connection.find do |connection| 111 connection.match?(request_uri, options) 112 end 113 end
# File lib/httpx/selector.rb 115 def find_mergeable_connection(connection) 116 each_connection.find do |ch| 117 ch != connection && ch.mergeable?(connection) 118 end 119 end
# File lib/httpx/selector.rb 87 def find_resolver(options) 88 res = @selectables.find do |c| 89 c.is_a?(Resolver::Resolver) && 90 options.resolver_options_match?(c.options) 91 end 92 93 res.multi if res 94 end
first time the registered selectables are added, there’s probably work to do.
# File lib/httpx/selector.rb 45 def initial_call 46 @selectables.each(&:initial_call) 47 end
# File lib/httpx/selector.rb 49 def next_tick 50 catch(:jump_tick) do 51 timeout = next_timeout 52 if timeout && timeout.negative? 53 @timers.fire 54 throw(:jump_tick) 55 end 56 57 begin 58 select(timeout) do |c| 59 c.log(level: 2) { "[#{c.state}] selected from selector##{object_id} #{" after #{timeout} secs" unless timeout.nil?}..." } 60 61 c.call 62 end 63 64 @timers.fire 65 rescue TimeoutError => e 66 @timers.fire(e) 67 end 68 end 69 end
register io.
# File lib/httpx/selector.rb 127 def register(io) 128 return if @selectables.include?(io) 129 130 @selectables << io 131 end
# File lib/httpx/selector.rb 71 def terminate 72 # array may change during iteration 73 selectables = @selectables.reject(&:inflight?) 74 75 selectables.delete_if do |sel| 76 sel.terminate 77 sel.state == :closed 78 end 79 80 until selectables.empty? 81 next_tick 82 83 selectables &= @selectables 84 end 85 end