Class: IO::Reactor

Inherits:
Object
  • Object
show all
Defined in:
lib/io/reactor.rb

Overview

An object-oriented multiplexing asynchronous IO reactor class.

Constant Summary collapse

Version =

Class constants

/([\d\.]+)/.match( %q{$Revision: 1.13 $} )[1]
Rcsid =
%q$Id: reactor.rb,v 1.13 2003/08/04 23:56:14 deveiant Exp $
ValidEvents =
[:read, :write, :error]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeReactor

Create and return a new IO reactor object.



74
75
76
77
78
79
80
81
82
83
# File 'lib/io/reactor.rb', line 74

def initialize
	@handles		= Hash::new {|hsh,key|
		hsh[ key ] = {
			:events		=> [],
			:handler	=> nil,
			:args		=> [],
		}
	}
	@pendingEvents	= Hash::new {|hsh,key| hsh[ key ] = []}
end

Instance Attribute Details

#handlesObject (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.



93
94
95
# File 'lib/io/reactor.rb', line 93

def handles
  @handles
end

#pendingEventsObject (readonly)

The Hash of unhandled events which occurred in the last call to #poll, keyed by handle.



97
98
99
# File 'lib/io/reactor.rb', line 97

def pendingEvents
  @pendingEvents
end

Instance Method Details

#clearObject

Clear all registered handles from the poll object. Returns the handles that were cleared.



204
205
206
207
208
209
210
211
# File 'lib/io/reactor.rb', line 204

def clear
	rv = @handles.keys

	@pendingEvents.clear
	@handles.clear

	return rv
end

#disableEvents(io, *events) ⇒ Object

Remove the specified events from the list that will be polled for on the given io handle.

Raises:

  • (RuntimeError)


142
143
144
145
146
# File 'lib/io/reactor.rb', line 142

def disableEvents( 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.

Returns:

  • (Boolean)


273
274
275
# File 'lib/io/reactor.rb', line 273

def empty?
	@handles.empty?
end

#enableEvents(io, *events) ⇒ Object

Add the specified events to the list that will be polled for on the given io handle.



135
136
137
# File 'lib/io/reactor.rb', line 135

def enableEvents( io, *events )
	@handles[ io ][:events] |= events
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 pendingEvents 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.



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/io/reactor.rb', line 240

def poll( timeout=-1 ) # :yields: io, eventMask
	timeout = timeout.to_f
	@pendingEvents.clear
	count = 0

	unless @handles.empty?
		timeout = nil if timeout < 0
		eventedHandles = self.getPendingEvents( 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.
		eventedHandles.each {|io,events|
			count += 1
			events.each {|ev|
				args = @handles[ io ][:args]

				if @handles[ io ][:handler]
					@handles[ io ][:handler].call( io, ev, *args )
				elsif block_given?
					yield( io, ev, *args )
				else
					@pendingEvents[io].push( ev )
				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.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/io/reactor.rb', line 116

def register( io, *args, &handler )
	events = [:read, :write, :error] & args
	args -= events

	self.unregister( io )
	self.enableEvents( io, *events )
	if handler
		self.setHandler( io, *args, &handler )
	else
		self.setArgs( io, *args )
	end

	return self
end

#registered?(io) ⇒ Boolean

Returns true if the specified io is registered with the poll object.

Returns:

  • (Boolean)


197
198
199
# File 'lib/io/reactor.rb', line 197

def registered?( io )
	return @handles.has_key?( io )
end

#removeArgs(io) ⇒ Object

Remove the arguments for the given handle to the given args.



180
181
182
# File 'lib/io/reactor.rb', line 180

def removeArgs( io )
	return @handles[ io ][:args].clear
end

#removeHandler(io) ⇒ Object

Remove and return the handler for events on the given io handle.



162
163
164
165
166
167
# File 'lib/io/reactor.rb', line 162

def removeHandler( io )
	rval = @handles[ io ][:handler]
	@handles[ io ][:handler] = nil
	self.removeArgs( io )
	return rval
end

#setArgs(io, *args) ⇒ Object

Set the additional arguments to pass to the handler for the given io handle on each event to the given args.



172
173
174
175
176
# File 'lib/io/reactor.rb', line 172

def setArgs( io, *args )
	rval = @handles[ io ][:args]
	@handles[ io ][:args] = args
	return rval
end

#setHandler(io, *args, &handler) ⇒ Object

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.



153
154
155
156
157
158
# File 'lib/io/reactor.rb', line 153

def setHandler( io, *args, &handler )
	rval = @handles[ io ][:handler]
	@handles[ io ][:handler] = handler
	self.setArgs( 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.



188
189
190
191
# File 'lib/io/reactor.rb', line 188

def unregister( io )
	@pendingEvents.delete( io )
	@handles.delete( io )
end