[MacRuby-devel] Dispatch gem - proxy object

Alan Skipp al_skipp at fastmail.fm
Tue Jan 25 15:31:32 PST 2011


Hi everyone,
After the recent discussion about gcd and thread safety I took a look at the Dispatch gem (proxy object in particular). I though I'd try and improve efficiency, as all method calls are currently directed through method_missing to the delegate object. 

One attempt I made was to dynamically define methods in method_missing so that subsequent calls would be more efficient. I realised the naivety of this approach when one queue was busily defining the method whilst other queues were calling method_missing - much pain ensued.

The next approach might be more promising: remove method_missing and instead define all methods of the delegate object in initialize. It appears to work most of the time, but unfortunately crashes are not infrequent. Is there anything obviously wrong about the initialize method below? 

Cheers,

Alan

------

require 'delegate'

module Dispatch

  class Proxy < SimpleDelegator

    attr_accessor :__group__, :__queue__, :__sync__

    def initialize(delegate, group=Group.new, queue=Dispatch::Queue.concurrent)
      super(delegate)
      @__serial__ = Dispatch::Queue.for(self)
      @__group__ = group
      @__queue__ = queue
      @__retval__ = nil

      delegate.public_methods.each do |meth|
        (class << self; self; end).class_eval do
          define_method meth do |*args, &block|
            if block.nil? then
              @__serial__.sync { @__retval__ = __getobj__.__send__(meth, *args) }
              return @__retval__
            end
            queue = @__queue__ # copy in case it changes while in flight
            @__serial__.async(@__group__) do
              retval = __getobj__.__send__(meth, *args)
              queue.async(@__group__) { block.call(retval) }
            end
          end
        end
      end

    end

end


More information about the MacRuby-devel mailing list