Class: IO::Reactor
- Inherits:
-
Object
- Object
- IO::Reactor
- Defined in:
- lib/io/reactor.rb
Overview
An object-oriented multiplexing asynchronous IO mechanism for Ruby.
Synopsis
reactor = IO::Reactor.new
data_to_send = "some stuff to send"
reader, writer = IO.pipe
# Read from the reader end of the pipe until the writer finishes
reactor.register( reader, :read ) do |io,event|
if io.eof?
reactor.unregister( io )
io.close
else
puts io.read( 256 )
end
end
# Write to the writer end of the pipe until there's no data left
reactor.register( writer, :write ) do |io,event|
bytes = io.write( data_to_send )
data_to_send.slice!( 0, bytes )
if data_to_send.empty?
reactor.unregister( io )
io.close
end
end
# Now pump the reactor until both sides are done
reactor.poll until reactor.empty?
Author
Michael Granger <[email protected]>
Copyright © 2002-2008 The FaerieMUD Consortium. All rights reserved.
This module is free software. You may use, modify, and/or redistribute this software under the same terms as Ruby itself.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Version
$Id: reactor.rb 86 2008-08-19 23:41:58Z deveiant $
Constant Summary collapse
- SVNRev =
SVN Revision
%q$Rev: 86 $
- SVNId =
SVN Id
%q$Id: reactor.rb 86 2008-08-19 23:41:58Z deveiant $
- VERSION =
Package version
'1.0.4'
- VALID_EVENTS =
List of valid event types, in the order IO#select returns them
[:read, :write, :error]
Instance Attribute Summary collapse
-
#handles ⇒ Object
readonly
The Hash of handles (instances of IO or its subclasses) associated with the reactor.
-
#pending_events ⇒ Object
(also: #pendingEvents)
readonly
The Hash of unhandled events which occurred in the last call to #poll, keyed by handle.
Instance Method Summary collapse
-
#clear ⇒ Object
Clear all registered handles from the poll object.
-
#disable_events(io, *events) ⇒ Object
(also: #disableEvents)
Remove the specified
events
from the list that will be polled for on the givenio
handle. -
#empty? ⇒ Boolean
Returns
true
if no handles are associated with the receiver. -
#enable_events(io, *events) ⇒ Object
(also: #enableEvents)
Add the specified
events
to the list that will be polled for on the givenio
handle. -
#event_enabled?(io, event) ⇒ Boolean
(also: #has_event_enabled?)
Returns
true
if the specifiedevent
is enabled for the givenio
. -
#initialize ⇒ Reactor
constructor
Create and return a new IO reactor object.
-
#poll(timeout = -1 )) ⇒ Object
Poll the handles registered to the reactor for pending events.
-
#register(io, *args, &handler) ⇒ Object
(also: #add)
Register the specified IO object with the reactor for events given as
args
. -
#registered?(io) ⇒ Boolean
Returns
true
if the givenio
handle is registered with the reactor. -
#remove_args(io) ⇒ Object
(also: #removeArgs)
Remove the arguments for the given handle to the given
args
. -
#remove_handler(io) ⇒ Object
(also: #removeHandler)
Remove and return the handler for events on the given
io
handle. -
#set_args(io, *args) ⇒ Object
(also: #setArgs)
Set the additional arguments to pass to the handler for the given
io
handle on each event to the givenargs
. -
#set_handler(io, *args, &handler) ⇒ Object
(also: #setHandler)
Set the handler for events on the given
io
handle to the specifiedhandler
. -
#unregister(io) ⇒ Object
(also: #remove)
Remove the specified
io
from the receiver’s list of registered handles, if present.
Constructor Details
#initialize ⇒ Reactor
Create and return a new IO reactor object.
78 79 80 81 82 83 84 85 86 87 |
# File 'lib/io/reactor.rb', line 78 def initialize @handles = Hash.new {|hsh,key| hsh[ key ] = { :events => [], :handler => nil, :args => [], } } @pending_events = Hash.new {|hsh,key| hsh[ key ] = []} end |
Instance Attribute Details
#handles ⇒ Object (readonly)
The Hash of handles (instances of IO or its subclasses) associated with the reactor. The keys are the IO objects, and the values are a Hash of event/s => handler.
97 98 99 |
# File 'lib/io/reactor.rb', line 97 def handles @handles end |
#pending_events ⇒ Object (readonly) Also known as: pendingEvents
The Hash of unhandled events which occurred in the last call to #poll, keyed by handle.
101 102 103 |
# File 'lib/io/reactor.rb', line 101 def pending_events @pending_events end |
Instance Method Details
#clear ⇒ Object
Clear all registered handles from the poll object. Returns the handles that were cleared.
223 224 225 226 227 228 229 230 |
# File 'lib/io/reactor.rb', line 223 def clear rv = @handles.keys @pending_events.clear @handles.clear return rv end |
#disable_events(io, *events) ⇒ Object Also known as: disableEvents
Remove the specified events
from the list that will be polled for on the given io
handle.
154 155 156 157 158 |
# File 'lib/io/reactor.rb', line 154 def disable_events( io, *events ) raise RuntimeError, "Cannot disable the :error event" if events.include?( :error ) @handles[ io ][:events] -= events end |
#empty? ⇒ Boolean
Returns true
if no handles are associated with the receiver.
295 296 297 |
# File 'lib/io/reactor.rb', line 295 def empty? @handles.empty? end |
#enable_events(io, *events) ⇒ Object Also known as: enableEvents
Add the specified events
to the list that will be polled for on the given io
handle.
146 147 148 |
# File 'lib/io/reactor.rb', line 146 def enable_events( io, *events ) @handles[ io ][:events] |= events end |
#event_enabled?(io, event) ⇒ Boolean Also known as: has_event_enabled?
Returns true
if the specified event
is enabled for the given io
.
163 164 165 166 167 |
# File 'lib/io/reactor.rb', line 163 def event_enabled?( io, event ) return false unless @handles.key?( io ) return true if event == :error # Error is always enabled for all handles return @handles[ io ][ :events ].include?( event ) end |
#poll(timeout = -1 )) ⇒ Object
Poll the handles registered to the reactor for pending events. The following event types are defined:
:read
-
Data may be read from the handle without blocking.
:write
-
Data may be written to the handle without blocking.
:error
-
An error has occurred on the handle. This event type is always enabled, regardless of whether or not it is passed as one of the
events
.
Any handlers specified when the handles were registered are run for those handles with events. If a block is given, it will be invoked once for each handle which doesn’t have an explicit handler. If no block is given, events without explicit handlers are inserted into the reactor’s pending_events
attribute.
The timeout
argument is the number of floating-point seconds to wait for an event before returning (ie., fourth argument to the underlying select()
call); negative timeout values will cause #poll to block until there is at least one event to report.
This method returns the number of handles on which one or more events occurred.
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/io/reactor.rb', line 259 def poll( timeout=-1 ) # :yields: io, eventMask timeout = timeout.to_f @pending_events.clear count = 0 unless @handles.empty? timeout = nil if timeout < 0 evented_handles = self.get_pending_events( timeout ) # For each event of each io that had an event happen, call any # associated callback, or any provided block, or failing both of # those, add the event to the hash of unhandled pending events. evented_handles.each do |io,events| count += 1 events.each do |ev| # Don't continue if the io was unregistered by an earlier handler break unless @handles.key?( io ) args = @handles[ io ][:args] if @handles[ io ][:handler] @handles[ io ][:handler].call( io, ev, *args ) elsif block_given? yield( io, ev, *args ) else @pending_events[io].push( ev ) end end end end return count end |
#register(io, *args, &handler) ⇒ Object Also known as: add
Register the specified IO object with the reactor for events given as args
. The reactor will test the given io
for the events specified whenever #poll is called. See the #poll method for a list of valid events. If no events are specified, only :error
events will be polled for.
If a handler
is specified, it will be called whenever the io
has any of the specified events
occur to it. It should take at least two parameters: the io
and the event.
If args
contains any objects except the Symbols ‘:read
’, ‘:write
’, or ‘:error
’, and a handler
is specified, they will be saved and passed to handler for each event.
Registering a handle will unregister any previously registered event/handler+arguments pairs associated with the handle.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/io/reactor.rb', line 121 def register( io, *args, &handler ) events = VALID_EVENTS & args args -= events self.unregister( io ) self.enable_events( io, *events ) if handler self.set_handler( io, *args, &handler ) else self.set_args( io, *args ) end return self end |
#registered?(io) ⇒ Boolean
Returns true
if the given io
handle is registered with the reactor.
139 140 141 |
# File 'lib/io/reactor.rb', line 139 def registered?( io ) return @handles.key?( io ) end |
#remove_args(io) ⇒ Object Also known as: removeArgs
Remove the arguments for the given handle to the given args
.
205 206 207 |
# File 'lib/io/reactor.rb', line 205 def remove_args( io ) return @handles[ io ][:args].clear end |
#remove_handler(io) ⇒ Object Also known as: removeHandler
Remove and return the handler for events on the given io
handle.
185 186 187 188 189 190 |
# File 'lib/io/reactor.rb', line 185 def remove_handler( io ) rval = @handles[ io ][:handler] @handles[ io ][:handler] = nil self.remove_args( io ) return rval end |
#set_args(io, *args) ⇒ Object Also known as: setArgs
Set the additional arguments to pass to the handler for the given io
handle on each event to the given args
.
196 197 198 199 200 |
# File 'lib/io/reactor.rb', line 196 def set_args( io, *args ) rval = @handles[ io ][:args] @handles[ io ][:args] = args return rval end |
#set_handler(io, *args, &handler) ⇒ Object Also known as: setHandler
Set the handler for events on the given io
handle to the specified handler
. If any args
are present, they will be passed as an exploded array to the handler for each event. Returns the previously-registered handler, if any.
175 176 177 178 179 180 |
# File 'lib/io/reactor.rb', line 175 def set_handler( io, *args, &handler ) rval = @handles[ io ][:handler] @handles[ io ][:handler] = handler self.set_args( io, *args ) return rval end |
#unregister(io) ⇒ Object Also known as: remove
Remove the specified io
from the receiver’s list of registered handles, if present. Returns the handle if it was registered, or nil
if it was not.
214 215 216 217 |
# File 'lib/io/reactor.rb', line 214 def unregister( io ) @pending_events.delete( io ) @handles.delete( io ) end |