module Utilrb::EventLoop::Forwardable

The EventLoop::Forwardable module provides delegation of specified methods to a designated object like the ruby ::Forwardable module but defers the method call to a thread pool of an event loop if a callback is given. After the call returned the callback is called from the event loop thread while it is processing its event at the end of each step.

To ensure thread safety for all kind of objects the event loop defers only one method call per object in parallel even if the method is called without any callback. For this mechanism a sync key is used which is by default the designated object but can be set to any custom ruby object. If a method call is thread safe the sync key can be set to nil allowing the event loop to call it in parallel while another none thread safe method call of the designated object is processed.

@note It is not possible to delegate methods where the target method needs

a code block.

@author Alexander Duda <Alexander.Duda@dfki.de>

Public Instance Methods

def_event_loop_delegator(accessor,event_loop, method, options = Hash.new ) click to toggle source

Defines a method as delegator instance method with an optional alias name ali.

Method calls to ali will be delegated to accessor.method. If an error occurres during proccessing it will be raised like in the case of the original object but also forwarded to the error handlers of event loop.

Method calls to ali(*args,&block) will be delegated to accessor.method(*args) but called from a thread pool. Thereby the code block is used as callback called from the main thread after the call returned. If an error occurred it will be:

* given to the callback as second argument 
* forwarded to the error handlers of the event loop
* raised at the beginning of the next step if not marked as known error

To overwrite an error the callback can return :ignore_error or a new instance of an error. In an event of an error the error handlers of the event loop will not be called or called with the new error instance.

ali do |result,exception|
   if exception
       MyError.new
   else
      puts result
   end
end

ali do |result,exception|
   if exception 
       :ignore_error
   else
      puts result
   end
end

If the callback accepts only one argument the callback will not be called in an event of an error but the error will still be forwarded to the error handlers.

If the result shall be filtered before returned a filter method can be specified which is called from the event loop thread just before the result is returned.

@example

class Dummy
    # non thread safe method
    def test(wait)
        sleep wait
        Thread.current
    end

    # thread safe method
    def test_thread_safe(wait)
        sleep wait
        Thread.current
    end
end
class DummyAsync
    extend Utilrb::EventLoop::Forwardable
    def_event_loop_delegator :@obj,:@event_loop,:test,:alias => :atest
    def_event_loop_delegator :@obj,:@event_loop,:test_thread_safe,:sync_key => false

    def initialize(event_loop)
        @event_loop = event_loop
        @obj = Dummy.new
    end
end

event_loop = EventLoop.new
test = DummyAsync.new(event_loop)
puts test.atest 2
test.atest 2 do |result|
    puts result
end
test.thread_safe 2 do |result|
    puts result
end
sleep(0.1)
event_loop.step

@param [Symbol] accessor The symbol for the designated object. @param [Symbol] event_loop The event loop accessor. @param [Symbol] method The method called on the designated object. @param [Hash] options The options @option options [Symbol] :alias The alias of the method @option options [Symbol] :sync_key The sync key @option options [Symbol] :filter The filter method @option options [Symbol] :on_error Method which is called if an error occured @option options [class] :known_errors Known errors which will be rescued but still be forwarded. @see sync

# File lib/utilrb/event_loop.rb, line 824
def def_event_loop_delegator(accessor,event_loop, method, options = Hash.new )
    Forward.def_event_loop_delegator(self,accessor,event_loop,method,options)
end
def_event_loop_delegators(accessor,event_loop, *methods) click to toggle source
# File lib/utilrb/event_loop.rb, line 828
def def_event_loop_delegators(accessor,event_loop, *methods)
    Forward.def_event_loop_delegators(self,accessor,event_loop,*methods)
end
forward_to(accessor,event_loop,options = Hash.new,&block) click to toggle source
# File lib/utilrb/event_loop.rb, line 832
def forward_to(accessor,event_loop,options = Hash.new,&block)
    obj = Forward.new(self,accessor,event_loop,options)
    obj.instance_eval(&block)
end