Class: IOReactor

Inherits:
Object show all
Defined in:
lib/mega/ioreactor.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

#initializeIOReactor

Create and return a new IO reactor object.



102
103
104
105
106
107
108
109
110
111
# File 'lib/mega/ioreactor.rb', line 102

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.



121
122
123
# File 'lib/mega/ioreactor.rb', line 121

def handles
  @handles
end

#pendingEventsObject (readonly)

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



125
126
127
# File 'lib/mega/ioreactor.rb', line 125

def pendingEvents
  @pendingEvents
end

Instance Method Details

#clearObject

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



232
233
234
235
236
237
238
239
# File 'lib/mega/ioreactor.rb', line 232

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)


170
171
172
173
174
# File 'lib/mega/ioreactor.rb', line 170

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)


301
302
303
# File 'lib/mega/ioreactor.rb', line 301

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.



163
164
165
# File 'lib/mega/ioreactor.rb', line 163

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.



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/mega/ioreactor.rb', line 268

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.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/mega/ioreactor.rb', line 144

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)


225
226
227
# File 'lib/mega/ioreactor.rb', line 225

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

#removeArgs(io) ⇒ Object

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



208
209
210
# File 'lib/mega/ioreactor.rb', line 208

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

#removeHandler(io) ⇒ Object

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



190
191
192
193
194
195
# File 'lib/mega/ioreactor.rb', line 190

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.



200
201
202
203
204
# File 'lib/mega/ioreactor.rb', line 200

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.



181
182
183
184
185
186
# File 'lib/mega/ioreactor.rb', line 181

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.



216
217
218
219
# File 'lib/mega/ioreactor.rb', line 216

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