Class: IO::Event::Debug::Selector
- Inherits:
-
Object
- Object
- IO::Event::Debug::Selector
- Defined in:
- lib/io/event/debug/selector.rb
Overview
Enforces the selector interface and delegates operations to a wrapped selector instance.
You can enable this in the default selector by setting the ‘IO_EVENT_DEBUG_SELECTOR` environment variable. In addition, you can log all selector operations to a file by setting the `IO_EVENT_DEBUG_SELECTOR_LOG` environment variable. This is useful for debugging and understanding the behavior of the event loop.
Defined Under Namespace
Modules: Forwarders
Class Method Summary collapse
-
.wrap(selector, env = ENV) ⇒ Object
Wrap the given selector with debugging.
Instance Method Summary collapse
-
#blocking_operation_wait(operation) ⇒ Object
Run the given blocking operation and wait for its completion.
-
#close ⇒ Object
Close the selector.
-
#idle_duration ⇒ Object
The idle duration of the underlying selector.
-
#initialize(selector, log: nil) ⇒ Selector
constructor
Initialize the debug selector with the given selector and optional log.
-
#io_read(fiber, io, buffer, length, offset = 0) ⇒ Object
Read from the given IO, forwarded to the underlying selector.
-
#io_wait(fiber, io, events) ⇒ Object
Wait for the given IO, forwarded to the underlying selector.
-
#io_write(fiber, io, buffer, length, offset = 0) ⇒ Object
Write to the given IO, forwarded to the underlying selector.
-
#log(message) ⇒ Object
Log the given message.
-
#now ⇒ Object
The current time.
-
#process_wait(*arguments) ⇒ Object
Wait for the given process, forwarded to the underlying selector.
-
#push(fiber) ⇒ Object
Push the given fiber to the selector ready list, such that it will be resumed on the next call to #select.
-
#raise(fiber, *arguments, **options) ⇒ Object
Raise the given exception on the given fiber.
-
#ready? ⇒ Boolean
Check if the selector is ready.
-
#respond_to?(name, include_private = false) ⇒ Boolean
Forward the given method to the underlying selector.
-
#resume(*arguments) ⇒ Object
Resume the given fiber with the given arguments.
-
#select(duration = nil) ⇒ Object
Select for the given duration, forwarded to the underlying selector.
-
#transfer ⇒ Object
Transfer from the calling fiber to the selector.
-
#wakeup ⇒ Object
Wakeup the the selector.
-
#yield ⇒ Object
Yield to the selector.
Constructor Details
#initialize(selector, log: nil) ⇒ Selector
Initialize the debug selector with the given selector and optional log.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/io/event/debug/selector.rb', line 42 def initialize(selector, log: nil) @selector = selector @readable = {} @writable = {} @priority = {} unless Fiber.current == selector.loop Kernel::raise "Selector must be initialized on event loop fiber!" end @log = log install_optional_forwarders(selector) end |
Class Method Details
.wrap(selector, env = ENV) ⇒ Object
Wrap the given selector with debugging.
28 29 30 31 32 33 34 35 36 |
# File 'lib/io/event/debug/selector.rb', line 28 def self.wrap(selector, env = ENV) log = nil if log_path = env["IO_EVENT_DEBUG_SELECTOR_LOG"] log = File.open(log_path, "w") end return self.new(selector, log: log) end |
Instance Method Details
#blocking_operation_wait(operation) ⇒ Object
Run the given blocking operation and wait for its completion.
155 156 157 158 |
# File 'lib/io/event/debug/selector.rb', line 155 def blocking_operation_wait(operation) log("Waiting for blocking operation #{operation.inspect}") @selector.blocking_operation_wait(operation) end |
#close ⇒ Object
Close the selector.
101 102 103 104 105 106 107 108 109 110 |
# File 'lib/io/event/debug/selector.rb', line 101 def close log("Closing selector") if @selector.nil? Kernel::raise "Selector already closed!" end @selector.close @selector = nil end |
#idle_duration ⇒ Object
The idle duration of the underlying selector.
73 74 75 |
# File 'lib/io/event/debug/selector.rb', line 73 def idle_duration @selector.idle_duration end |
#io_read(fiber, io, buffer, length, offset = 0) ⇒ Object
Read from the given IO, forwarded to the underlying selector.
173 174 175 176 |
# File 'lib/io/event/debug/selector.rb', line 173 def io_read(fiber, io, buffer, length, offset = 0) log("Reading from IO #{io.inspect} with buffer #{buffer}; length #{length} offset #{offset}") @selector.io_read(fiber, io, buffer, length, offset) end |
#io_wait(fiber, io, events) ⇒ Object
Wait for the given IO, forwarded to the underlying selector.
167 168 169 170 |
# File 'lib/io/event/debug/selector.rb', line 167 def io_wait(fiber, io, events) log("Waiting for IO #{io.inspect} for events #{events.inspect}") @selector.io_wait(fiber, io, events) end |
#io_write(fiber, io, buffer, length, offset = 0) ⇒ Object
Write to the given IO, forwarded to the underlying selector.
179 180 181 182 |
# File 'lib/io/event/debug/selector.rb', line 179 def io_write(fiber, io, buffer, length, offset = 0) log("Writing to IO #{io.inspect} with buffer #{buffer}; length #{length} offset #{offset}") @selector.io_write(fiber, io, buffer, length, offset) end |
#log(message) ⇒ Object
Log the given message.
87 88 89 90 91 92 93 |
# File 'lib/io/event/debug/selector.rb', line 87 def log() return unless @log Fiber.blocking do @log.puts("T+%10.1f; %s" % [now, ]) end end |
#now ⇒ Object
The current time.
80 81 82 |
# File 'lib/io/event/debug/selector.rb', line 80 def now Process.clock_gettime(Process::CLOCK_MONOTONIC) end |
#process_wait(*arguments) ⇒ Object
Wait for the given process, forwarded to the underlying selector.
161 162 163 164 |
# File 'lib/io/event/debug/selector.rb', line 161 def process_wait(*arguments) log("Waiting for process with #{arguments.inspect}") @selector.process_wait(*arguments) end |
#push(fiber) ⇒ Object
Push the given fiber to the selector ready list, such that it will be resumed on the next call to #select.
133 134 135 136 |
# File 'lib/io/event/debug/selector.rb', line 133 def push(fiber) log("Pushing fiber #{fiber.inspect} to ready list") @selector.push(fiber) end |
#raise(fiber, *arguments, **options) ⇒ Object
Raise the given exception on the given fiber.
142 143 144 145 |
# File 'lib/io/event/debug/selector.rb', line 142 def raise(fiber, *arguments, **) log("Raising exception on fiber #{fiber.inspect} with #{arguments.inspect}") @selector.raise(fiber, *arguments, **) end |
#ready? ⇒ Boolean
Check if the selector is ready.
150 151 152 |
# File 'lib/io/event/debug/selector.rb', line 150 def ready? @selector.ready? end |
#respond_to?(name, include_private = false) ⇒ Boolean
Forward the given method to the underlying selector.
185 186 187 |
# File 'lib/io/event/debug/selector.rb', line 185 def respond_to?(name, include_private = false) @selector.respond_to?(name, include_private) end |
#resume(*arguments) ⇒ Object
Resume the given fiber with the given arguments.
119 120 121 122 |
# File 'lib/io/event/debug/selector.rb', line 119 def resume(*arguments) log("Resuming fiber with #{arguments.inspect}") @selector.resume(*arguments) end |
#select(duration = nil) ⇒ Object
Select for the given duration, forwarded to the underlying selector.
190 191 192 193 194 195 196 197 |
# File 'lib/io/event/debug/selector.rb', line 190 def select(duration = nil) log("Selecting for #{duration.inspect}") unless Fiber.current == @selector.loop Kernel::raise "Selector must be run on event loop fiber!" end @selector.select(duration) end |
#transfer ⇒ Object
Transfer from the calling fiber to the selector.
113 114 115 116 |
# File 'lib/io/event/debug/selector.rb', line 113 def transfer log("Transfering to event loop") @selector.transfer end |
#wakeup ⇒ Object
Wakeup the the selector.
96 97 98 |
# File 'lib/io/event/debug/selector.rb', line 96 def wakeup @selector.wakeup end |
#yield ⇒ Object
Yield to the selector.
125 126 127 128 |
# File 'lib/io/event/debug/selector.rb', line 125 def yield log("Yielding to event loop") @selector.yield end |